Я создал стандартный вектор и переместил на него кучу объектов с помощью стандартного перемещения, например:
vector<unique_ptr<Foo> > myVec;
unique_ptr<Foo> a = make_unique<Foo>();
unique_ptr<Foo> b = make_unique<Foo>();
myVec.push_back(move(a));
myVec.push_back(move(b));
Все идет нормально.
Позже я передаю ссылку myVec в функцию и пытаюсь получить доступ к данным в векторе с помощью []-операторов.
void someFunc(vector<unique_ptr<Foo> > &myVec)
{
Foo* anObj = myVec[0];
}
После некоторого чтения я предполагаю, что этот подход не будет работать, потому что вектор std попытается сделать копию, и если я не предоставлю конструктор копирования на Foo, который избегает фактического создания копии, он никогда не будет работать. Я прав? Я думаю, что видел несколько сообщений об использовании итераторов, но я бы предпочел не делать этого, если мне это не нужно.
РЕДАКТИРОВАТЬ1:
Мне удалось обойти это следующим образом (используя итератор, а затем получить необработанный указатель)
void someFunc(vector<unique_ptr<Foo> > &myVec)
{
int offset = 0; // Or some other offset into the vector
auto it = myVec.begin() + offset;
Foo* anObj = it.get();
// ... Do something using anObj here...
}
Я бы подумал, что это правильный путь, если вы не попытаетесь по глупости сохранить anObj, а затем где-то вручную освободить его. Я мог бы, конечно, временно передать право собственности, пока я не закончу с этим, а затем вернуть право собственности, но это кажется такой проблемой. Любые мысли о вышеупомянутом подходе?
Заранее спасибо, /Джимми
Только что опубликовал обновление EDIT, где я использую метод get(). Правильно ли я понимаю, и это нормальный подход? Я предполагаю, что он был «в основном» разработан, чтобы заставить unique_ptr работать с устаревшим кодом, где вам нужно это сделать. Мой код новый, поэтому я бы не хотел, чтобы в нем уже был уродливый шаблон. Насколько я понимаю, мое решение в части EDIT верное. Если нет, то я был бы очень рад узнать и исправить это
Предпосылка, кажется, заключается в том, что myVec[0]
делает копию. Это не.
@LightnessRacesinOrbit: Вы правы. Должно быть, я сделал какую-то другую ошибку, я снова обновил код, и, похоже, он работает нормально. Foo* anObj = myVec[0].get() работает нормально.
Переменная anObj
должна быть типа std::unique_ptr<Foo>
, а не Foo*
.
Код должен быть:
std::unique_ptr<Foo>& anObj{ myVec[ 0 ] };
Или
Foo* anObj{ myVec[ 0 ].get( ) };
Разве это не сведется к той же проблеме с использованием оператора []? Я получу "... ошибка: использование удаленной функции 'std::unique_ptr<_Tp, _Dp>::unique_pt...", потому что он пытается использовать конструктор копирования?
Я не вижу здесь ничего, требующего конструктора копирования. []
не делает копию. Если вы получили эту ошибку сейчас, значит, вы неправильно скопировали код, предложенный WBuck.
Должно быть, я сделал какую-то ошибку, предложения здесь работают нормально. Спасибо за помощь, ребята
С++ не решает за вас, использовать ли копирование или присваивание ссылки.
Вы должны справиться с этим самостоятельно.
=
в строке объявления, например int y = x;
, вы используете конструктор копирования.&
перед ней, например int & y = x;
вы берете ссылку x
и сохраняете ее в y
.В вашем примере у вас есть 2 проблемы:
unique_ptr<Foo>
Foo*
, что
неправильно.unique_ptr<Foo>
, чтобы вы
следует объявить ссылку unique_ptr<Foo>
следующим образом:
unique_ptr<Foo> & ref = myVec[0];
Если вы посмотрите на документы для
std::unique_ptr
, вы увидите, есть ли несколько способов вернуть указатель: а именноrelease()
иget()
- прочитайте о них и решите, что вы хотите сделать, или используйте указатель непосредственно изmyVec[0]
вместо его копирования. в любом месте.