C ++ передает структуру или объект по значению - PullRequest
3 голосов
/ 29 июля 2010

У меня есть это:

enum Units { Pounds, Kilos };

struct Configuration
{
    const Units units;
    const char *name;

    inline Configuration(Units pUnits, char *pName) : units(pUnits)
    {
        name = strdup(pName);
    }

    inline ~Configuration() { free((void *)name); }
};

Я передавал один из них такому методу:

Configuration cc(Kilos, "abc");
cdao->write(cc);

Я получал неприятные сбои от этого, пока не попытался переопределить методвзять ссылку:

Configuration cc(Kilos, "abc");
cdao->write(&cc);

И теперь все работает.

Но как структура по значению может быть связана с памятью?

Ответы [ 4 ]

6 голосов
/ 29 июля 2010

Тот факт, что вы используете strdup, указывает на то, что с вашим кодом что-то не так, и неправильно то, что у вас нет конструктора копирования.Каждый раз, когда у вас есть деструктор, вам почти наверняка понадобится конструктор копирования, который будет правильно копировать объект при вызове по значению.

Чтобы улучшить ваш код:

  • создайте конструктор копирования и, возможно, оператор присваивания, который правильно выделит и скопирует строку

  • еще лучше, избавьтесь от strdup - используйте строку std: ;, в этом случае вам не понадобится деструктор, копия ctor или операция присваивания.

  • избавиться от "встроенные "ключевые слова - они ничего не делают.

2 голосов
/ 29 июля 2010

Вы не указали свой собственный конструктор копирования или оператор присваивания.Таким образом, когда вы делаете копию или присваивание, используются сгенерированные компилятором конструкторы копирования и операторы присваивания, которые на самом деле не делают правильных действий в этом случае.Они просто копируют каждый элемент, чтобы вы получили два объекта конфигурации, ссылающихся на одинаковый массив символов.И оба объекта конфигурации чувствуют себя ответственными за удаление массива, что почти наверняка приводит к ошибке «двойного удаления».

Имейте в виду « правило трех ».Проблема в том, что указатель ведет себя не так, как вы этого хотите.Если бы вы использовали std :: string в качестве члена, вам не пришлось бы писать свой собственный конструктор копирования, деструктор, оператор присваивания.Это связано с тем, что сгенерированные компилятором команды просто вызывают соответствующие операции для своих членов, а string-member уже обрабатывает это правильно - в отличие от указателя на char.

1 голос
/ 29 июля 2010

Вы должны добавить свой struct конструктор копирования и обработать имя char *; (имеется в виду, выделить и удалить память, инициализировать со значением).

В любом случае, не рекомендуется использовать char * для строк. Используйте std :: string, которая будет обрабатывать все для вас.

1 голос
/ 29 июля 2010

Когда вы вызываете его без ссылки, он копирует units и *name, но не значения внутри *name.Поэтому, когда этот временный объект разрушается, он освобождает *name от всех экземпляров Configuration.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...