зауженное расширение времени жизни
От: Molchalnik  
Дата: 08.11.19 03:11
Оценка:
Смотрел недавно видео, и там наш буржуйский коллега красиво расписывал, как получать повисшие (dangled) ссылки

Не понял один момент
struct A {};

struct B {
  A a_;
  A get() { return a_;}
};

namespace my {
template <typename T> T const & min( T const & a, T const &b ) { return a<b ? b: a; }
}

void main() {

B t1, t2;

const A& t3 = t1.get(); // сработало нормально, из-за temporary timelife extension

const A& dangled_reference = my::min( t1.get(), t2.get() ); // повисшая ссылка
}


Так вот, товарищ утверждал, что в
const A& dangled_reference = my::min( t1.get(), t2.get() );

будет повисшая ссылка,мотивируя это тем, что temporary timelife extension не работает через rvalue

Я читал последний стандарт п. 6.10 про glvalue, prvalue, rvalue и xvalue
так же п. 15.2 про расширение времени жизни переменной, и не смог связать стандарт и утверждения коллеги.

Буду благодарен, если вы объясните мне вопрос, желательно с опорой на стандарт. Возможно, я просто плохо перевожу и распарсиваю наш главный мануал.
Re: зауженное расширение времени жизни
От: andyp  
Дата: 08.11.19 07:23
Оценка: 2 (1)
Здравствуйте, Molchalnik, Вы писали:


M>Буду благодарен, если вы объясните мне вопрос, желательно с опорой на стандарт. Возможно, я просто плохо перевожу и распарсиваю наш главный мануал.


Если подойдёт объяснение с cppreference, то оно здесь:
https://en.cppreference.com/w/cpp/language/reference_initialization

Секция Lifetime of a temporary.
Re[2]: зауженное расширение времени жизни
От: σ  
Дата: 08.11.19 11:19
Оценка:
A>Если подойдёт объяснение с cppreference, то оно здесь:
A>https://en.cppreference.com/w/cpp/language/reference_initialization

A>Секция Lifetime of a temporary.


Прям как старые бабки: "открой такую-то группу вконтакте и промотай до поста от xx.yy.zzzz".
Прямую ссылку дать никак? https://en.cppreference.com/w/cpp/language/reference_initialization#Lifetime_of_a_temporary
Re[3]: зауженное расширение времени жизни
От: andyp  
Дата: 08.11.19 12:12
Оценка: :)
Здравствуйте, σ, Вы писали:

σ>Прям как старые бабки: "открой такую-то группу вконтакте и промотай до поста от xx.yy.zzzz".

σ>Прямую ссылку дать никак? https://en.cppreference.com/w/cpp/language/reference_initialization#Lifetime_of_a_temporary

О как. Не умел отродясь и, боюсь, снова забуду. Склероз, внучек.
Re[2]: зауженное расширение времени жизни
От: B0FEE664  
Дата: 08.11.19 14:13
Оценка:
Здравствуйте, andyp, Вы писали:

A>Секция Lifetime of a temporary.


(since C++20)
struct A {
  int&& r;
};
A a1{7}; // OK, lifetime is extended
A a2(7); // well-formed, but dangling reference

OMG! Кто-нибудь может мне объяснить зачем понадобилось расширять инициализацию с круглыми скобками? Чтобы было легче допустить ошибку забыв написать конструктор?
И каждый день — без права на ошибку...
Re[3]: зауженное расширение времени жизни
От: andyp  
Дата: 08.11.19 14:41
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>OMG! Кто-нибудь может мне объяснить зачем понадобилось расширять инициализацию с круглыми скобками? Чтобы было легче допустить ошибку забыв написать конструктор?


Расширять на агрегаты? Имхо как раз за тем, чтобы меньше писать тривиального кода. Ну любит народ круглые скобочки , хочет инициализировать так же как и классы с конструктором.
Re[4]: зауженное расширение времени жизни
От: B0FEE664  
Дата: 08.11.19 15:02
Оценка:
Здравствуйте, andyp, Вы писали:

A>Расширять на агрегаты? Имхо как раз за тем, чтобы меньше писать тривиального кода. Ну любит народ круглые скобочки , хочет инициализировать так же как и классы с конструктором.


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

struct A
{
  int x;
  int y; 
};

A pt{ .x= 2, .y = 3 };

Вот чего не хватает, так это такого:
A pt{ .x= 2, .y = .x };
И каждый день — без права на ошибку...
Re[5]: зауженное расширение времени жизни
От: σ  
Дата: 08.11.19 16:15
Оценка: 1 (1)
BFE>Вот чего не хватает, так это такого:
BFE>
BFE>A pt{ .x= 2, .y = .x };
BFE>


A pt { .x = 2, .y = pt.x };
Re[6]: зауженное расширение времени жизни
От: B0FEE664  
Дата: 08.11.19 17:09
Оценка:
Здравствуйте, σ, Вы писали:

BFE>>Вот чего не хватает, так это такого:

BFE>>
BFE>>A pt{ .x= 2, .y = .x };
BFE>>


σ>
A pt { .x = 2, .y = pt.x };


Хмм. А разве, формально, это не использование переменной pt до её инициализации?
И каждый день — без права на ошибку...
Re[7]: зауженное расширение времени жизни
От: σ  
Дата: 08.11.19 17:28
Оценка:
BFE>>>Вот чего не хватает, так это такого:
BFE>>>
BFE>>>A pt{ .x= 2, .y = .x };
BFE>>>


σ>>
A pt { .x = 2, .y = pt.x };


BFE>Хмм. А разве, формально, это не использование переменной pt до её инициализации?


[basic.life]/6 говорит что получать доступ к non-static data members или вызывать non-static member functions через указатель на объект чей lifetime не начался это UB.
[basic.life]/7 описывает поведение glvalues, ссылающихся на объект, чей lifetime не начался. И там UB только если вызывать функции, но не получать доступ к data members.

Так что, видимо, всё норм.
Re[5]: зауженное расширение времени жизни
От: andyp  
Дата: 08.11.19 20:12
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Здравствуйте, andyp, Вы писали:


A>>Расширять на агрегаты? Имхо как раз за тем, чтобы меньше писать тривиального кода. Ну любит народ круглые скобочки , хочет инициализировать так же как и классы с конструктором.


BFE>Ну не знаю. Можно же использовать фигурные, тем более, что теперь можно указывать названия полей:


Народ имхо привык к старым правилам преобразования типов и хочет продолжать ими пользоваться. А случае фигурных скобок правила пожестче.

BFE>Вот чего не хватает, так это такого:

BFE>
BFE>A pt{ .x= 2, .y = .x };
BFE>


Когда читал про это, тоже думал, что мне этого не хватает. Но вот как-то обхожусь. Сам не знаю почему, но у меня простенькие агрегаты с малым количеством полей получаются
Re[2]: зауженное расширение времени жизни
От: Molchalnik  
Дата: 08.11.19 23:09
Оценка:
Здравствуйте, andyp, Вы писали:

A>Здравствуйте, Molchalnik, Вы писали:



M>>Буду благодарен, если вы объясните мне вопрос, желательно с опорой на стандарт. Возможно, я просто плохо перевожу и распарсиваю наш главный мануал.


A>Если подойдёт объяснение с cppreference, то оно здесь:

A>https://en.cppreference.com/w/cpp/language/reference_initialization

A>Секция Lifetime of a temporary.



вот это ключевое для вопроса из приведённого источника

In general, the lifetime of a temporary cannot be further extended by "passing it on": a second reference, initialized from the reference to which the temporary was bound, does not affect its lifetime.

В общем случае, нельзя рассчитывать на сквозное продление времени жизни временных переменных: уже на вторая ссылка, инициализированная от той, к которой временная переменная была привязана в первые, не влияет на её[временной переменной] время жизни.

Это почти всё делает ясным, но хотелось бы ссылочку на стандарт
Отредактировано 08.11.2019 23:10 Molchalnik . Предыдущая версия .
Re[3]: зауженное расширение времени жизни
От: rg45 СССР  
Дата: 10.11.19 22:04
Оценка:
Здравствуйте, Molchalnik, Вы писали:

M>вот это ключевое для вопроса из приведённого источника

M>

M>In general, the lifetime of a temporary cannot be further extended by "passing it on": a second reference, initialized from the reference to which the temporary was bound, does not affect its lifetime.

M>Это почти всё делает ясным, но хотелось бы ссылочку на стандарт

Это описано в Temporary objects: https://timsong-cpp.github.io/cppwp/class.temporary#6, пунткт 6.11:

The lifetime of a temporary bound to the returned value in a function return statement ([stmt.return]) is not extended; the temporary is destroyed at the end of the full-expression in the return statement.

--
Не можешь достичь желаемого — пожелай достигнутого.
Re[4]: зауженное расширение времени жизни
От: Molchalnik  
Дата: 10.11.19 22:35
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, Molchalnik, Вы писали:


M>>вот это ключевое для вопроса из приведённого источника

M>>

M>>In general, the lifetime of a temporary cannot be further extended by "passing it on": a second reference, initialized from the reference to which the temporary was bound, does not affect its lifetime.

M>>Это почти всё делает ясным, но хотелось бы ссылочку на стандарт

R>Это описано в Temporary objects: https://timsong-cpp.github.io/cppwp/class.temporary#6, пунткт 6.11:


R>

R>The lifetime of a temporary bound to the returned value in a function return statement ([stmt.return]) is not extended; the temporary is destroyed at the end of the full-expression in the return statement.


спасибо! Но есть ещё утверждение автора примера о том, что у rvalue не возможно расширить время жизни, только скопировать. Если на 6.11 я ещё натыкался, то вот про rvalue я вообще ничего не нашёл.
Отредактировано 10.11.2019 22:36 Molchalnik . Предыдущая версия .
Re[5]: зауженное расширение времени жизни
От: rg45 СССР  
Дата: 10.11.19 23:11
Оценка: 2 (1)
Здравствуйте, Molchalnik, Вы писали:

R>>

R>>The lifetime of a temporary bound to the returned value in a function return statement ([stmt.return]) is not extended; the temporary is destroyed at the end of the full-expression in the return statement.


M>спасибо! Но есть ещё утверждение автора примера о том, что у rvalue не возможно расширить время жизни, только скопировать. Если на 6.11 я ещё натыкался, то вот про rvalue я вообще ничего не нашёл.


Я думаю, здесь имеет место какое-то не совсем верное толкование его высказываний. Во-первых, заметно некоторое размытие терминологии: в контескте обсуждения продления времени жизни речь идет всегда о времени жизни временных объектов. Которые материализуются как раз при биндинге ссылок именно к rvalue выражениям (prvalue, если быть точным):

https://timsong-cpp.github.io/cppwp/class.temporary#2

The materialization of a temporary object is generally delayed as long as possible in order to avoid creating unnecessary temporary objects. [
Note: Temporary objects are materialized:
— when binding a reference to a prvalue
— . . .


А во-вторых, важным является то, что (какая-то) ссылка биндится к временному объекту, какая именно это ссылка (rvalue или lvalue), совсем не важно. Поэтому rvalue ссылка способна продлевать время жизни временного объекта с тем же успехом, что и константная lvalue ссылка. И в этой же главе можно найти примеры:

https://timsong-cpp.github.io/cppwp/class.temporary#6

template<typename T> using id = T;

int i = 1;
int&& a = id<int[3]>{1, 2, 3}[i];           // temporary array has same lifetime as a
const int& b = static_cast<const int&>(0);  // temporary int has same lifetime as b
int&& c = cond ? id<int[3]>{1, 2, 3}[i] : static_cast<int&&>(0);
                                            // exactly one of the two temporaries is lifetime-extended

--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 10.11.2019 23:21 rg45 . Предыдущая версия . Еще …
Отредактировано 10.11.2019 23:14 rg45 . Предыдущая версия .
Re[7]: зауженное расширение времени жизни
От: Mr.Delphist  
Дата: 11.11.19 16:40
Оценка:
Здравствуйте, B0FEE664, Вы писали:

σ>>
A pt { .x = 2, .y = pt.x };


BFE>Хмм. А разве, формально, это не использование переменной pt до её инициализации?


Подозреваю, здесь то же правило, что и на списках инициализации внутри конструкторов — играет роль лишь порядок описания полей класса, но никак не порядок упоминания инициализаторов. Т.е. если в описании поле "игрек" идёт после поля "икс", то такой финт легален, т.к. "pt.x" уже будет проинициализирован первым, даже если мы напишем так:

A pt { .y = pt.x, .x = 2 };


Но это лишь интуитивное подозрение, конечно. Ибо пути Комитета неисповедимы...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.