Russian Qt Forum
Ноябрь 25, 2024, 14:06 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 2 3 [4]   Вниз
  Печать  
Автор Тема: rvalue и operator ->  (Прочитано 24518 раз)
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #45 : Декабрь 25, 2018, 18:32 »

И второй вопрос - а это вообще ок переиспользовать мувнутый объект?

стандарт говорит, что перемещенный объект находится в состоянии unspecified

что означает, что точное его состоянии не известно.
(и на него нельзя закладываться. оно может меняться от версии к версии)
однако, его деструктор, конструкторы, и сеттеры полностью в рабочем состоянии.

то бишь, ты имеешь полное право назначить перемещенному объекту новое состояние,
и продолжать с ним работать как ни в чем не бывало.

Код:
process( std::move(stdstring_value) );

// <--- unspecified

stdstring_value = "hello";

//<--- regular state

Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 584


Просмотр профиля
« Ответ #46 : Декабрь 25, 2018, 19:09 »

Но у меня вопрос, внутри && ф-ии мемберы же тоже lvalue, нет?
да. 
поскольку у этих мемберов есть имена.

В примере

Код
C++ (Qt)
Test().m_value;
static_cast< Test && >( test ).m_value;
::std::move( test ).m_value;
 

тоже присутствует имя m_value, но это всё rvalue значения.

И, еще отмечу, что move без потребителя не является перемещением, отсюда и появилась моя первоначальная ремарка (здесь).
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #47 : Декабрь 26, 2018, 11:09 »

В примере
тоже присутствует имя m_value, но это всё rvalue значения.

тёмная сторона с++.
мир тонких граблей, двусмысленных трактовок,
и поведений у различных компиляторов ждут отважного путешественника
на этой стязе.

простой пример:

известный факт: константная ссылка на временный объект подливает время его жизни
до конца жизни самой ссылки.

https://ideone.com/mKHcSL

Код:
#include <iostream>

struct data
{
    ~data() { std::cout << "data: destructor\n"; }
};

int main()
{
    std::cout << "begin...\n";
    {
     const auto& ref = data{};
     std::cout << "work with temporary...\n";
    }
    std::cout << "finished!\n";
}


но что будет, если мы возьмем константную ссылочку не на весь агрегат,
а только на какой то один из мемберов?

Код:
#include <iostream>

struct data
{
    ~data() { std::cout << "data: destructor\n"; }
};

struct sample
{
    data value;

    ~sample() { std::cout << "sample: destructor\n"; }
};

int main()
{
    std::cout << "begin...\n";
    {
     const auto& ref = sample().value;
     std::cout << "work with temporary...\n";
    }
    std::cout << "finished!\n";
}
вывод в консоль:
Код:
begin...
work with temporary...
sample: destructor
data: destructor
finished!

продлевается жизнь всего агрегата.
отлично! - скажешь ты, - это логично.
раз время жизни мембера продлевается,
тогда нужно продлить время жизни и всего агрегата,
ведь без хозяина мембер существовать не может.

теперь оставляем в классе хозяине только POD-типы мемберов:

Код:
#include <iostream>

struct data
{
    ~data() { std::cout << "data: destructor\n"; }
};

struct sample
{
//data value;
int value;

    ~sample() { std::cout << "sample: destructor\n"; }
};

int main()
{
    std::cout << "begin...\n";
    {
     const auto& ref = sample().value;
     std::cout << "work with temporary...\n";
    }
    std::cout << "finished!\n";
}
вывод в консоль:
Код:
begin...
sample: destructor
work with temporary...
finished!

и о боже! деструктор агрегата отработал раньше, чем закончилось время жизни константной ссылки!
в этом случае мы получаем протухшую ссылку.
привет багам!

что примечательно:
на разных компиляторах с разными настройками оптимизации можно получить разные результаты.

вывод:
ну его нафиг: связываться с "временными мемберами".

практика показывает:
не нужно здесь искать какую то логику, и на что либо закладываться.


И, еще отмечу, что move без потребителя не является перемещением, отсюда и появилась моя первоначальная ремарка (здесь).

строго говоря, само название "move" не вполне, казалось бы, отражает свою функцию.
факт перемещения следует из контекста применения мува,
но не содержится в самом муве.


для чего вы хотите задействовать методы временного объекта?
какие вообще плюшки вы хотите поиметь таким образом?

на самом деле единственная плюшка временного объекта - факт, что он временный.
а значит его можно переместить.

во всех остальных случаях его "временность" не имеет никакого значения.

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

« Последнее редактирование: Декабрь 26, 2018, 11:18 от _Bers » Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 584


Просмотр профиля
« Ответ #48 : Декабрь 26, 2018, 12:00 »

для чего вы хотите задействовать методы временного объекта?
какие вообще плюшки вы хотите поиметь таким образом?

Моя цель - реализовать обертку над любым пользовательским типом данных, которая бы максимально была похоже на сам пользовательский тип, но добавляла дополнительные фитчи (особенности).
К таким особенностям относятся, например,
- выбор размещения: по месту владельца/в куче.
- ленивые вычисления: copy-on-write и т.п.
- потокобезопасность
- и др.

По отдельности, вместе, в любом порядке применения.

Так как предполагается возможность использования любого пользовательского типа, то приходится учитывать все возможные гипотетические случаи, которые могут быть реализованы (возможно кем-то в бреду) с помощью конструкций языка C++.
К такому случаю относится и возможность запрета языковыми конструкциями вызова методов для lvalue/rvalue значений.
Нужен он пользовательскому типу или нет, это дело самого пользователя. В конце концов, что не запрещено, то разрешено).
Язык позволяет такой сценарий применения, в котором не подразумевается никакой move, а только запрет вызова bar() с помощью lvalue значения

Код
C++ (Qt)
Test func ();
func().bar(); // Oк
Test test;
test.bar(); // Error
 

Обертка вокруг Test должна предоставлять ровно тоже самое.
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #49 : Декабрь 26, 2018, 17:21 »

Обертка вокруг Test должна предоставлять ровно тоже самое.
пускай возвращает ресурс по ссылке, будет ровно тоже самое.


Записан
Страниц: 1 2 3 [4]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.16 секунд. Запросов: 23.