Доступ к unique_ptrs в стандартном векторе - должен предоставить конструктор копирования?

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

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, а затем где-то вручную освободить его. Я мог бы, конечно, временно передать право собственности, пока я не закончу с этим, а затем вернуть право собственности, но это кажется такой проблемой. Любые мысли о вышеупомянутом подходе?

Заранее спасибо, /Джимми

Если вы посмотрите на документы для std::unique_ptr, вы увидите, есть ли несколько способов вернуть указатель: а именно release() и get() - прочитайте о них и решите, что вы хотите сделать, или используйте указатель непосредственно из myVec[0] вместо его копирования. в любом месте.

Tony Delroy 10.06.2019 19:26

Только что опубликовал обновление EDIT, где я использую метод get(). Правильно ли я понимаю, и это нормальный подход? Я предполагаю, что он был «в основном» разработан, чтобы заставить unique_ptr работать с устаревшим кодом, где вам нужно это сделать. Мой код новый, поэтому я бы не хотел, чтобы в нем уже был уродливый шаблон. Насколько я понимаю, мое решение в части EDIT верное. Если нет, то я был бы очень рад узнать и исправить это

Jim 10.06.2019 19:50

Предпосылка, кажется, заключается в том, что myVec[0] делает копию. Это не.

Lightness Races in Orbit 10.06.2019 19:50

@LightnessRacesinOrbit: Вы правы. Должно быть, я сделал какую-то другую ошибку, я снова обновил код, и, похоже, он работает нормально. Foo* anObj = myVec[0].get() работает нормально.

Jim 10.06.2019 20:05
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
77
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Переменная 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...", потому что он пытается использовать конструктор копирования?

Jim 10.06.2019 19:47

Я не вижу здесь ничего, требующего конструктора копирования. [] не делает копию. Если вы получили эту ошибку сейчас, значит, вы неправильно скопировали код, предложенный WBuck.

Lightness Races in Orbit 10.06.2019 19:49

Должно быть, я сделал какую-то ошибку, предложения здесь работают нормально. Спасибо за помощь, ребята

Jim 10.06.2019 20:07

С++ не решает за вас, использовать ли копирование или присваивание ссылки.

Вы должны справиться с этим самостоятельно.

  • Если вы объявляете новую переменную и используете оператор = в строке объявления, например int y = x;, вы используете конструктор копирования.
  • Если вы объявите переменную с & перед ней, например int & y = x; вы берете ссылку x и сохраняете ее в y.

В вашем примере у вас есть 2 проблемы:

  1. Вы пытаетесь присвоить unique_ptr<Foo>Foo*, что неправильно.
  2. Вы хотите иметь ссылку unique_ptr<Foo>, чтобы вы следует объявить ссылку unique_ptr<Foo> следующим образом: unique_ptr<Foo> & ref = myVec[0];

Другие вопросы по теме