Будет ли auto_ptr защищать от этого? - PullRequest
4 голосов
/ 09 марта 2009

Мне не совсем понятно, поможет ли auto_ptr в этом случае:

class A
{
  A(const B& member)
   : _member(B)
  {};

...
  const B& _member;
};


A generateA() {
   auto_ptr<B> smart(new B());
   A myA(*smart);
   return myA;
}

Будет ли справка myA._member действительной, когда smart покидает пределы объема? Если auto_ptr не является ответом, что это?

РЕДАКТИРОВАТЬ: я вижу, где я всех запутал; Я должен вернуть myA за пределы области действия, поэтому я забочусь о том, чтобы _правильный элемент действовал после выхода из области действия smart.

Ответы [ 3 ]

6 голосов
/ 09 марта 2009

Это тебе не поможет. _member станет висящей ручкой. Это связано с тем, что auto_ptr гарантирует уничтожение в конце области действия: не более, а не менее .

Есть 2 возможных ответа.

  • Вы можете сделать тип _member boost::shared_ptr<const B>.
  • В качестве альтернативы, если класс B является маленьким , копируемым , мономорфным и идентичность объекта не требуется сохранять , вы можете сделать _member значение и сохранить там копию аргумента. Это, безусловно, самый простой вариант, но, очевидно, он весьма ограничен.

В ответ на ваше редактирование: Это действительно тот случай, о котором я говорил. Возвращая myA по значению, создается копия, а _member копия ссылается на уже уничтоженный локальный. Как описано, и shared_ptr, и семантика значений решают эту проблему.

2 голосов
/ 09 марта 2009

Класс auto_ptr является оберткой над обычными указателями. Они заботятся о перераспределении, когда стек разворачивается (вызывается деструктор auto_ptr, который в свою очередь освобождает ваш содержащийся объект).

Обратите внимание, что ваш A объект также создан в стеке. Когда область действия закончится, A и auto_ptr будут освобождены. Помимо этого, попытка доступа к объекту A приведет к ошибке времени компиляции.

Если предположить, что объект A был создан где-то за пределами блока, то у вас есть реальная проблема. Поскольку объект A хранит ссылку на объект B, вне области видимости блока эта ссылка становится недействительной.

Обратите внимание, что в C ++ 0x auto_ptr устарела. Вместо этого используйте unique_ptr. Взгляните на интеллектуальные указатели общего назначения , которые появляются в C ++ 0x.

0 голосов
/ 09 марта 2009
{
   auto_ptr<B> smart(new B());
   A myA(*smart);
}

И указатель, удерживаемый в «smart», и объект «myA» будут уничтожены в конце этой области. Но это должно быть то, что вы хотите с этим фрагментом кода.

Как только область действия заканчивается, myA будет уничтожено первым (объявлено последним).
Затем этот смарт будет уничтожен, а его деструктор удалит указатель.

Поскольку нет никакого способа сослаться на «умный» или «myA», я надеюсь, что вы хотите удалить указатель на этом этапе.

В качестве альтернативы вы можете сделать это:

{
    B  myB;
    A  myA(myB);
}
...