Время жизни объектов с операцией перемещения и пересылкой значения

Я хотел бы знать, если следующий код является действительным.
В частности, я озадачен временем жизни объектов, задействованных здесь, после вызова new_S.
Насколько я понимаю, T будет скопирован при обработке списка инициализаторов и, возможно, в конструкторе перемещения вектора.
А как насчет вектора RValue? это все еще действует после возвращения из new_S? Я бы сказал нет, но я точно не уверен

struct T
{
int t;
};

struct S
{
S(std::vector<T>&& s) : s_(std::forward<std::vector<T>>(s)) {}

std::vector<T> s_;
};

S* new_S()
{
return new S{{{1}, {2}, {3}}};
}

1

Решение

После возвращения из new_S нет вектора RValue (я предполагаю, что вы имеете в виду параметр ссылки rvalue для конструктора). Ссылка на значение существует только во время построения S.

Несколько слов к вашему коду: std::forward это работа здесь. Это нужно только для идеальной пересылки универсальных ссылок, и std::vector<T> не универсальный реф, а ревал (посмотреть здесь). использование std::move в этом случае.

Сказав это, вы не должны проходить мимо rvalue-ref в своем конструкторе. Вместо этого передайте по значению:

struct S
{
S(std::vector<T> s) : s_{std::move(s)} {}

std::vector<T> s_;
};

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

  • Если передано значение, s строится на основе аргумента, после этого s_ построено из s, Копии не сделаны.
  • Если передано lvalue, s после этого создается копия, s_ построено из s, Сделана только одна необходимая копия.

Последнее, но не менее важное: не используйте сырые указатели и new/delete, Вместо этого используйте умные указатели:

unique_ptr<S> new_S()
{
return std::make_unique<S>({{1}, {2}, {3}});
}

make_unique поставляется с C ++ 14, вы можете легко свернуть свой собственный, если у вашей библиотеки его еще нет.

Обновить:
Чтобы ответить на ваш вопрос о времени жизни объекта: В new_Sу вас есть в основном 4 или 5 объектов:

  • S, который создается и вектор внутри него
  • Список инициализаторов, который вы передаете конструктору
  • временный вектор, построенный из списка инициализаторов
  • в моем написании функции, параметр s это собственный объект.

Теперь что происходит:

  1. Список инициализатора используется для создания временного векторного объекта, который является значением, которое передается в конструктор. Во время создания временного блока выделяется один фрагмент памяти для размещения трех Т внутри вектора.
  2. В вашей записи параметр rvalue ref конструктора привязан к временному. В моем письме s инициализируется временным вызывающим конструктором перемещения вектора. После этого временный пустой и s владеет частью памяти с T
  3. В инициализации s_, параметр перемещен. Это означает, s_ получает движение построено из временного (в вашем письме) или из s (в моем письме). После этого временный /s пусты и s_ владеет порцией памяти, выделенной на шаге 1.

s_ правильно построен, и это действительный объект. Объект X становится только «недействительным» при перемещении, т.е. при вызове move(X), Объект Y вы строите, перемещая другой объект X к нему (имеется в виду: создать его с помощью auto Y = move(X);) никогда не является недействительным Инвалидирование объектов в конструкции было бы крайне плохо и бесполезно, C ++ был бы неработающим языком.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]