Передача параметров объектов C ++ с динамически выделяемой памятью - PullRequest
0 голосов
/ 06 марта 2011

Я новичок в мире C ++, но у меня есть некоторый опыт работы с C и я прочитал несколько уроков по C ++.Теперь создание объектов в C ++ кажется довольно простым и хорошо работает для меня, если у класса есть только атрибуты, которые являются значениями (не указателями).

Теперь, когда я пытаюсь создать объекты, которые выделяют память в конструкторедля некоторых их атрибутов я выясняю, как именно такие объекты передаются между функциями.Простой пример такого класса:

class A {
  int *a;
public:
  A(int value) {
    this->a = new int;
    *(this->a) = value;
  }
  ~A() {
    delete this->a;
  }
  int getValue() const { return this->a; }
}

Я хочу использовать класс и передать его по значению другим функциям и т. Д. По крайней мере, эти примеры должны работать без создания утечек памяти или ошибок двойного освобождения.

A f1() {
  // some function that returns A
  A value(5);
  // ...
  return value;
}
void f2(A a) {
  // takes A as a parameter
  // ...
}

A a = f1();
A b = a;
f2(a);
f2(f1());

Класс A является неполным, потому что я должен переопределить operator= и A(A& oldValue), чтобы решить некоторые из этих проблем.Насколько я понимаю, реализация этих методов по умолчанию просто копирует значение членов, из-за чего деструктор вызывается дважды для одних и тех же значений указателя.

Прав ли я, а что еще мне не хватает?Кроме того, знаете ли вы какой-нибудь хороший учебник, который объясняет эту проблему?

Ответы [ 3 ]

2 голосов
/ 06 марта 2011

Когда вы передаете подобный объект, вы создаете копию этого объекта.Чтобы этого не делать, вы должны передать константную ссылку ...

void f2(A const & a)
{
}

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

2 голосов
/ 06 марта 2011

Используйте контейнеры и интеллектуальные указатели.

Например, std::vector для массива динамической длины или boost::shared_ptr для динамически размещаемого отдельного объекта.

Не занимайтесь непосредственно управлением временем жизни объекта.

Приветствия и hth.,

1 голос
/ 06 марта 2011

В частности, должен реализовать конструктор копирования, который правильно копирует указатель памяти для переменной a .Любой конструктор по умолчанию просто скопировал бы область памяти для переменной a , которая, очевидно, подлежит двойному удалению.

Даже при этом:

  A value(5);
  // ...
  return value;

не будет работать, потому что, когда A выпадает из области видимости (в конце раздела), вызывается оператор удаления для A, что приводит к удалению суб-переменной a и делает память недействительной.

...