在VC ++中将malloc()用于C ++字符串对象的问题,但是new没问题

时间:2019-02-07 12:34:35

标签: c++ visual-c++ malloc new-operator

这是一个简单的代码:

#include <iostream>
#include <string>

typedef struct Car{
    std::string model;
} Car;

std::string get_model() {
    std::string str = "Maserati";
    return str;
}

int main() {
    const int nCars = 2;
    //Car *list = new Car[nCars];                   // works everywhere g++/VC++
    Car *list = (Car *)malloc(nCars * sizeof(Car)); // works in g++, not VC++

    list[0].model = get_model();
    std::cout << "model=" << list[0].model << std::endl;    
    // delete[] list;
    free(list);
    return 0;
}

当我在g ++中使用malloc()或new时没有问题。但是,malloc()在Visual C ++中不起作用。分配C ++类对象时是否应该始终使用new?

(债务人)<> << / p>

3 个答案:

答案 0 :(得分:3)

在要删除对象时,您在分配内存时没有调用构造函数或调用析构函数。这就是new[]delete[]对您的作用,因此请使用它们-或更好地使用智能指针-甚至更好地使用标准容器(例如std::vector)为您保留对象

您的代码中添加了缺少的部分:

#include <iostream>
#include <string>

struct Car {
    std::string model;

    Car() { std::cout << "ctor\n"; }
    ~Car() { std::cout << "dtor\n"; }
};

int main() {
    const int nCars = 2;

    // allocate memory
    Car *list = (Car *)malloc(nCars * sizeof(Car));

    // manually calling constructors
    for(int i=0; i<nCars; ++i) {
        new(&list[i]) Car();
    }

    // use objects here

    // manually calling destructors
    for(int i=0; i<nCars; ++i) {
        list[i].~Car();
    }

    // freeing memory
    free(list);
}

比较使用new[]delete[]

int main() {
    const int nCars = 2;

    // create cars
    Car* list = new Car[nCars];

    // use objects here

    // delete cars
    delete[] list;
}

与使用容器比较:

int main() {
    const int nCars = 2;

    // create cars
    std::vector<Car> list(nCars);

    // use objects here
}

答案 1 :(得分:2)

是的

虽然说“在C ++中永远不要使用malloc()”是错误的,但绝对不应该使用malloc()来实例化一个类。

请记住,从某种意义上讲,C ++是一种混合语言,因为它有效地支持了几乎完整的C子集,并添加了C ++功能的超集。在使用malloc()intchar等内置类型时,float可以发挥作用。

但是,对于对象,必须使用new。您可能确实发现malloc()在很多情况下都可以使用,但是newdelete会导致调用构造函数和析构函数,这将永远不会执行。发生在malloc()free()上。

答案 2 :(得分:-3)

这里的问题是因为您正在为Car结构的std :: string分配内存,但是不调用std :: string构造函数。

您应该为数组中的每个项目调用一个新的placement,以调用构造函数并初始化Car结构中的std :: string字段:

int main() {
    const int nCars = 2;
    Car* list = (Car *)malloc(nCars * sizeof(Car));

    for (int i = 0; i < nCars; ++i)
        new(&list[i])Car();

    list[0].model = get_model();
    std::cout << "model=" << list[0].model << std::endl;
}

-原始答案-

这是我的原始答案(由于数组https://en.cppreference.com/w/cpp/language/new#Allocation可能需要额外的开销,因此不正确)

如果必须使用malloc,则建议您对返回的内存块使用就地构造函数:

int main() {
    const int nCars = 2;
    Car *list = new (malloc(nCars * sizeof(Car)))Car[nCars];

    list[0].model = get_model();
    std::cout << "model=" << list[0].model << std::endl;
    return 0;
}