Проблема использования malloc () для строкового объекта C ++ в VC ++, но не проблема с новым - PullRequest
0 голосов
/ 07 февраля 2019

Вот простой код:

#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;
}

Нет проблем, когда я использовал malloc () или new в g ++.Однако malloc () не работает в Visual C ++.Должен ли я использовать новый всегда, когда я выделяю объект класса C ++?

(должник) <> <</p>

Ответы [ 3 ]

0 голосов
/ 07 февраля 2019

Проблема здесь в том, что вы выделяете память для std :: string вашей структуры Car, но не вызываете конструктор std :: string.

Вы должны вызывать новое размещение для каждого элементав массиве для вызова конструктора и инициализации поля std :: string в структуре Car:

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;
}
0 голосов
/ 07 февраля 2019

Вы выделяете память без вызова конструктора или вызова деструктора, когда объект собирается быть удаленным.Это то, что 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
}
0 голосов
/ 07 февраля 2019

Да.

Хотя неправильно говорить «Никогда не используйте malloc() в C ++», безусловно, верно, что вам никогда не следует использовать malloc() для создания экземпляра класса.

Имейте в виду, что C ++, в некотором смысле, является гибридным языком в том смысле, что он эффективно поддерживает почти полное подмножество C и добавляет расширенный набор функций C ++.malloc() играет роль при использовании встроенных типов, таких как int, char, float и т. Д.

Для объектов, однако, необходимо использовать new.Возможно, вы обнаружили, что malloc() работает во многих случаях, но new и delete будут вызывать конструкторы и деструкторы, что никогда никогда не произойдет с malloc() и free().

...