Здравствуйте, T4r4sB, Вы писали:
TB>Из поля в локалку — перемещение. А вот return локалки уже сработал через rvo.
Никогда RVO не работал для "локалок". Для "локалок" МОЖЕТ сработать NRVO. А может не сработать. Это уже как компилятор решит. В отличие от RVO, NRVO не гарантируется, это всего лишь необязательная оптимизация. Но только это не относится к твоему случаю, так как у тебя "локалка" — это сслыка. И перемещение у тебя произошло как раз при выходе из функции, а вовсе не при взятии rvalue ссылки на поле. Само по себе взятие ссылки не влечё никакого перемещения. Перемещение происходит при ИСПОЛЬЗОВАНИИ rvalue ссылки. В данном случае при выполнении оператора return.
А для того, чтоб было так, как ты описал, тебе переменную temp нужно обявить как объектный тип, а не как ссылку: https://godbolt.org/z/4j7fjGcTe. Лишь с маленькой поправкой: не RVO, а NRVO. Правда, выхлоп программы от этого изменения никак не изменится Программа у тебя написана так, что позволяет определить, что перемещение произошло один раз. Но когда это произошло, этого не видно. А чтоб увидеть момент перемещения, можно слегка расширить отладочную печать: https://godbolt.org/z/d7fY5e8nh
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, rg45, Вы писали:
R>Но только это не относится к твоему случаю, так как у тебя "локалка" — это сслыка. И перемещение у тебя произошло как раз при выходе из функции, а вовсе не при взятии rvalue ссылки на поле.
Здравствуйте, T4r4sB, Вы писали: TB>Короче, нефиг объявлять переменные и возвращаемые типы с &&, у меня от этого крыша едет
Вот я, когда на С++ 11 переходил, тоже удивлялся насчет && в возвращаемом типе.
Непонятно, почему это вообще это не запрещено на уровне стандарта/компиляторов.
Есть мысли, когда локальные переменные и возвращаемые значения с && могут быть полезны?
S>- будет создавать полную копию всех данных. Как бы постоянная ловушка. Т.е. нужно не забывать писать:
S>
S>std::vector<uint8_t>& t = obj.getData();
S>
Можно обернуть vector в shared_ptr (и поле класса и тип возвращаемого значения getData().
Тоже не очень красиво выглядит, но зато думать насчет move и пр. NRVO уже не понадобится.
Либо std::span (но он только в C++20, хотя написать свой аналог для частного случая IMHO несложно).
то, что vector (и не только он) скрытно может копировать данные — это действительно проблема всей stl. Я бы решал её переопределением своего "пуританского" вектора (без блекджека).
template <typename T>
class greedy_vector : public std::vector<T> {
public:
using std::vector<T>::vector;
greedy_vector explicit_copy() const {
return *this;
}
private:
greedy_vector(const greedy_vector& other): std::vector<T>(other) {}
};
теперь просто так не скопируешь:
greedy_vector<int> data{100};
const auto copy = data; // ошибка
Здравствуйте, sergii.p, Вы писали:
SP>то, что vector (и не только он) скрытно может копировать данные — это действительно проблема всей stl. Я бы решал её переопределением своего "пуританского" вектора (без блекджека).
SP>
#include <vector>
template <typename T>
class greedy_vector : public std::vector<T> {
public:
using std::vector<T>::vector;
friend greedy_vector explicit_copy(const greedy_vector& orig) {
return greedy_vector(orig); // guaranteed RVO
}
private:
greedy_vector(const greedy_vector&) = default;
};
int main()
{
greedy_vector<int> data{100};
const auto copy = explicit_copy(data);
}
Благодаря guaranteed copy elision, такая реализация explicit_copy равнозначна конструктору, с практической точки зрения. И для конструктора копирования здесь вполне подойдет вариант, сгенерированный компилятором.
--
Справедливость выше закона. А человечность выше справедливости.
S>- будет создавать полную копию всех данных. Как бы постоянная ловушка.
Никакая это не ловушка. Это общепринятая практика. S>Т.е. нужно не забывать писать:
std::vector<uint8_t>& t = obj.getData();
const пропущен. S>И далее. Что если я захочу в итоге переместить данные, забрать владение у MyClass — как красивее оформить?
Написать метод swap S>