2012-01-24 4 views
6

Я хотел бы иметь вектор unique_ptr как член класса, который я делаю.Как объявить вектор unique_ptr как член данных класса?

class Foo { 
    [...] 

private: 
    vector<unique_ptr<Bar>> barList; 
} 

Но потом я начала получать загадочные сообщения об ошибках от VS2010 компилятора:

error C2248: 'std::unique_ptr<_Ty>::operator =' : cannot access private member declared in class 'std::unique_ptr<_Ty>' 

Наряду с несколькими линиями ошибок ниже того, что нырять в реализацию Microsoft о std::_Copy_impl<> ...

Я сменил заявление о членстве на

vector<unique_ptr<Bar>>* barList; 

И он компилируется. Но я не могу не задаться вопросом, почему я не могу сделать это так, как я изначально хотел? Для улыбок, я попробовал это, и это работает прекрасно:

vector<Bar> barList; 

Но теперь я теряю удобство unique_ptr. Я хочу мой торт, и я тоже хочу его съесть!

+0

Я смотрел на http://stackoverflow.com/questions/8553464/vector-as-a-class-member, и кажется, что ответ кажется, что объявление «вектора», как я, было просто замечательно. По какой-то причине, по-видимому, он вызывает незаконные копии при добавлении части 'unique_ptr'. –

+1

Как выглядит ваш конструктор копий и оператор присваивания? –

+0

Частное назначение, но копия была виновником. Перешел из 'unique_ptr' в' shared_ptr', когда понял, что использовал неправильную семантику собственности. –

ответ

10

Проблема заключается в том, что где-то ваш код пытается вызвать оператор «копирования-присваивания» Foo.

Это заставляет компилятор попытаться создать оператор присваивания копий, который вызывает операторы присваивания копий всех подобъектов Foo. В конце концов, это приводит к попытке скопировать unique_ptr, операцию, которая невозможна.

+0

Спасибо, что указали это. Компилятор вводил меня в заблуждение, потому что ошибка ссылалась на объявление участника и не упоминала оскорбительном коде, вызывающем копию. Я полагаю, что это недостаток VS2010 и, надеюсь, улучшится с более новыми версиями. У моего класса 'Foo' есть конструктор копирования, и я пытался скопировать вектор из источника' Foo'. Совместное владение кажется лучшим решением, поэтому переход на 'shared_ptr' сделал трюк. –

+1

Похоже на ошибку в VS2010. Я получаю эту ошибку, даже если мой код никогда не пытается вызвать копирование. Отключение оператора = с объявлением как private (следовательно = delete не поддерживается) решает проблему. – tr3w

-2

Вы не можете использовать unique_ptr в векторе, потому что векторная реализация сильно зависит от значений присваивает оператор, который является приватным в unique_ptr. Используйте shared_ptr из boost или другой умной реализации ptr из C++ 11.

+6

'unique_ptr' отлично работает в' vector'. [См.] (Http://ideone.com/riLhp) –

+0

Контейнеры C++ 11 необходимы для работы с типами только для перемещения, такими как 'unique_ptr'. – bames53

+0

Я имел в виду, как он это использовал. Но все же, благодарю Тебя, я не знал о emplace_back. – aambrozkiewicz

4

unique_ptr не имеет семантики копий, поэтому вы не можете использовать какие-либо методы, которые бы скопировали содержащийся объект. Вы можете сделать это с помощью ссылок rvalue, используя std::move в местах (-ах), которые он пытается сделать копию. Не видя своего кода, я не могу сказать, где это будет.

Если он компилируется во второй форме, либо вы не использовали один и тот же код, либо есть ошибка компилятора. Оба должны потерпеть неудачу одинаково.

Ваш третий пример хранения по значению является самым простым способом, если ваши объекты не являются большими и дорогими для хранения/копирования по значению.

+1

'auto_ptr' - это тот, который не подчиняется обычной семантике копирования,' unique_ptr' просто не ** имеет ** копию семантики – Grizzly

+0

Ответы вашего и Mankarse очень похожи. Его, однако, заставило меня понять, что мне нужно продолжать охоту на ведьм за нарушительный код (ваш ответ более тонко изложил эту проблему). Вы оба заслуживаете принятого ответа. Спасибо за помощь! –

2

Часто отсутствует std::move(iUniquePtr) (например, при использовании push_back).

0

An выдержки из www.cplusplus.com

std::unique_ptr::operator= 

unique_ptr Назначение Объект приобретает право собственности на содержание иксы, в том числе как хранится указатель и хранится Deleter (наряду с ответственностью удаления объекта в какой-то момент). Любой объект, принадлежащий объекту unique_ptr перед вызовом, удаляется (как если бы был вызван деструктор unique_ptr).

Но есть предупреждение тоже:

Эта страница описывает функцию введенную последней редакции стандарта C++ (2011). Старые компиляторы могут не поддерживать его.

MSVC 2010 определяет operator= как закрытый (несъемный), но поддерживает метод swap.