Re[9]: Про красивость работы с std::vector
От: T4r4sB Россия  
Дата: 15.03.25 12:45
Оценка:
Здравствуйте, rg45, Вы писали:


R>Ну так и в этом случае не RVO, а перемещение. Что и видно по выхлопу.


Из поля в локалку — перемещение. А вот return локалки уже сработал через rvo.
Но он мог бы просто написать return std::move для поля
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[2]: Про красивость работы с std::vector
От: Shmj Ниоткуда  
Дата: 15.03.25 12:46
Оценка:
Здравствуйте, Muxa, Вы писали:

M>А если вернуть результат как &&?


А тут смотрите какая ловушка то: https://rsdn.org/forum/cpp/8911389.flat
Автор: Shmj
Дата: 15.03 15:28


Получается, после уничтожения Wrapper — оъект уничтожается, хотя владение вроде забрали.
=сначала спроси у GPT=
Re[10]: Про красивость работы с std::vector
От: rg45 СССР  
Дата: 15.03.25 13:07
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Из поля в локалку — перемещение. А вот return локалки уже сработал через rvo.


Никогда RVO не работал для "локалок". Для "локалок" МОЖЕТ сработать NRVO. А может не сработать. Это уже как компилятор решит. В отличие от RVO, NRVO не гарантируется, это всего лишь необязательная оптимизация. Но только это не относится к твоему случаю, так как у тебя "локалка" — это сслыка. И перемещение у тебя произошло как раз при выходе из функции, а вовсе не при взятии rvalue ссылки на поле. Само по себе взятие ссылки не влечё никакого перемещения. Перемещение происходит при ИСПОЛЬЗОВАНИИ rvalue ссылки. В данном случае при выполнении оператора return.

А для того, чтоб было так, как ты описал, тебе переменную temp нужно обявить как объектный тип, а не как ссылку: https://godbolt.org/z/4j7fjGcTe. Лишь с маленькой поправкой: не RVO, а NRVO. Правда, выхлоп программы от этого изменения никак не изменится Программа у тебя написана так, что позволяет определить, что перемещение произошло один раз. Но когда это произошло, этого не видно. А чтоб увидеть момент перемещения, можно слегка расширить отладочную печать: https://godbolt.org/z/d7fY5e8nh
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 15.03.2025 13:13 rg45 . Предыдущая версия .
Re[11]: Про красивость работы с std::vector
От: T4r4sB Россия  
Дата: 15.03.25 13:11
Оценка: :)
Здравствуйте, rg45, Вы писали:

R>Но только это не относится к твоему случаю, так как у тебя "локалка" — это сслыка. И перемещение у тебя произошло как раз при выходе из функции, а вовсе не при взятии rvalue ссылки на поле.


Да, походу так и есть: https://godbolt.org/z/39MjzzPq5

Короче, нефиг объявлять переменные и возвращаемые типы с &&, у меня от этого крыша едет
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[12]: Про красивость работы с std::vector
От: rg45 СССР  
Дата: 15.03.25 13:22
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Да, походу так и есть: https://godbolt.org/z/39MjzzPq5


Прикольно, независимо друг от друга мы с тобой написали идентичный код: https://godbolt.org/z/d7fY5e8nh
--
Справедливость выше закона. А человечность выше справедливости.
Re[12]: Про красивость работы с std::vector
От: qaz77  
Дата: 15.03.25 13:23
Оценка:
Здравствуйте, T4r4sB, Вы писали:
TB>Короче, нефиг объявлять переменные и возвращаемые типы с &&, у меня от этого крыша едет

Вот я, когда на С++ 11 переходил, тоже удивлялся насчет && в возвращаемом типе.
Непонятно, почему это вообще это не запрещено на уровне стандарта/компиляторов.

Есть мысли, когда локальные переменные и возвращаемые значения с && могут быть полезны?
Re: Про красивость работы с std::vector
От: m2user  
Дата: 15.03.25 14:27
Оценка:
S>Не очень красиво что при обращении:

S>
S>std::vector<uint8_t> t = obj.getData();
S>


S>- будет создавать полную копию всех данных. Как бы постоянная ловушка. Т.е. нужно не забывать писать:


S>
S>std::vector<uint8_t>& t = obj.getData();
S>


Можно обернуть vector в shared_ptr (и поле класса и тип возвращаемого значения getData().
Тоже не очень красиво выглядит, но зато думать насчет move и пр. NRVO уже не понадобится.
Либо std::span (но он только в C++20, хотя написать свой аналог для частного случая IMHO несложно).
Отредактировано 15.03.2025 18:48 m2user . Предыдущая версия .
Re: Про красивость работы с std::vector
От: sergii.p  
Дата: 16.03.25 09:09
Оценка: 1 (1)
Здравствуйте, Shmj, Вы писали:

то, что 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; // ошибка
Re[2]: Про красивость работы с std::vector
От: rg45 СССР  
Дата: 16.03.25 10:25
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>то, что vector (и не только он) скрытно может копировать данные — это действительно проблема всей stl. Я бы решал её переопределением своего "пуританского" вектора (без блекджека).


SP>
SP>template <typename T>
SP>class greedy_vector : public std::vector<T> {
SP>public:
SP>    using std::vector<T>::vector;

SP>    greedy_vector explicit_copy() const {
SP>        return *this;
SP>    }

SP>private:
SP>    greedy_vector(const greedy_vector& other): std::vector<T>(other) {}
SP>};
SP>


SP>теперь просто так не скопируешь:


SP>
SP>greedy_vector<int> data{100};
SP>const auto copy = data; // ошибка
SP>


Я бы это задизайнил так:

http://coliru.stacked-crooked.com/a/68033678ff7f1a67

#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 равнозначна конструктору, с практической точки зрения. И для конструктора копирования здесь вполне подойдет вариант, сгенерированный компилятором.
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 16.03.2025 10:44 rg45 . Предыдущая версия . Еще …
Отредактировано 16.03.2025 10:43 rg45 . Предыдущая версия .
Отредактировано 16.03.2025 10:40 rg45 . Предыдущая версия .
Отредактировано 16.03.2025 10:39 rg45 . Предыдущая версия .
Отредактировано 16.03.2025 10:29 rg45 . Предыдущая версия .
Отредактировано 16.03.2025 10:28 rg45 . Предыдущая версия .
Re: Про красивость работы с std::vector
От: B0FEE664  
Дата: 17.03.25 15:10
Оценка: -1 :)
Здравствуйте, Shmj, Вы писали:

  Скрытый текст
S>Допустим такая обертка над std::vector:

S>
S>#include <vector>
S>#include <cstdint>
S>#include <cstring>

S>class MyClass
S>{
S>private:
S>    std::vector<uint8_t> data;

S>public:
S>    MyClass() : data(100) {}

S>    void setHeader(uint32_t value)
S>    {
S>        std::memcpy(data.data(), &value, sizeof(value));
S>    }

S>    // ... еще устанавливаем разные части бинарного пакета

S>    const std::vector<uint8_t>& getData() const
S>    {
S>        return data;
S>    }
S>};
S>


S>Не очень красиво что при обращении:

std::vector<uint8_t> t = obj.getData();

S>- будет создавать полную копию всех данных. Как бы постоянная ловушка.
Никакая это не ловушка. Это общепринятая практика.

S>Т.е. нужно не забывать писать:

std::vector<uint8_t>& t = obj.getData();

const пропущен.

S>И далее. Что если я захочу в итоге переместить данные, забрать владение у MyClass — как красивее оформить?

Написать метод swap

S>
S>std::vector<uint8_t> takeData()
S>{
S>    return std::move(data);
S>}
S>

Так можно, но зачем?

Человек, что боится забыть поставить '&' должен так же бояться забыть написать obj.takeData(); без присвоения
for(uint8_t n : obj.takeData())
  std::cout << ' ' << n;
std::cout << '\n';

// ой, obj пустой :(
И каждый день — без права на ошибку...
Отредактировано 17.03.2025 15:49 B0FEE664 . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.