Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > const reference to the temporary object


Автор: vinter 17.3.2009, 13:59
после прочтения http://herbsutter.spaces.live.com/blog/cns!2D4327CC297151BB!378.entry статтьи у меня появился резонный вопрос: WTF? Кто, что думает по поводу подобного?

Автор: InvalidProperty 17.3.2009, 14:16
В чем заключается вопрос? Подобные конструкции языка не являются ошибочными. Если же вопрос заключается в целесообразности такого использования, так я лучше приведу две цитаты:
"Си остр, как бритва, с помощью него можно создать как красивую статую, так и кровавое месиво" (Керниган)

"C - если вы захотите выстрелить себе в ногу, то сделаете без проблем.
C++ - вы можете выстрелить себе в ногу, даже если не хотели этого." (автор неизвестен)

Автор: vinter 17.3.2009, 14:38
Цитата(InvalidProperty @  17.3.2009,  15:16 Найти цитируемый пост)
 Подобные конструкции языка не являются ошибочными

почему не являются? Где это написано? Я не понимаю на каком основании продлевается время жизни объекта.

Автор: InvalidProperty 17.3.2009, 14:42
рассматривая объект класса string, можно совершенно определенно сказать, что время жизни продлевается на том основании, что объект будет существовать до тех пор, пока на него не закончатся ссылки. Ссылки всего 2. После выхода из функции - одна. Так почему же объект должен удаляться?

Автор: vinter 17.3.2009, 14:48
Цитата(InvalidProperty @  17.3.2009,  15:42 Найти цитируемый пост)
что время жизни продлевается на том основании, что объект будет существовать до тех пор, пока на него не закончатся ссылки

не забываем, что это С++ и garbage collector здесь отсутсвует, а значит понятия "пока на него не закончатся ссылки" в С++ несуществует, если мы не используем smart pointers(но это совершенно другая тема, здесь не об этом)

Автор: InvalidProperty 17.3.2009, 15:11
не забываем, что класс string построен именно таким образом, что его объект не уничтожится, пока на него не закончатся внутренние ссылки. Объект класса string не копируется при присваивании, увеличивается внутренний счетчик ссылок. Копирование происходит только при изменении объекта. При удалении счетчик ссылок уменьшается. Garbage collector тут совсем ни при чем.
В данном же случае, используется ссылка на функцию, возвращающую значение. Значение живет на момент выхода из функции. Тут мы для него заводим новую ссылку. Ссылка - это алиас переменной, альтернативное имя. Так почему же объект должен быть уничтоженным, если переменная еще жива в текущем контексте (я говорю про тот момент, когда заводится ссылка const string& s = f();)? 

Автор: Lazin 17.3.2009, 15:16
Тут подсчет ссылок не используется, просто, компилятор располагает объект в стеке так, что-бы его время жизни было больше чем время жизни ссылок на него. Напомню, что это работает только для объектов в стеке.

Автор: xvr 17.3.2009, 15:26
Цитата(vinter @ 17.3.2009,  14:38)
Цитата(InvalidProperty @  17.3.2009,  15:16 Найти цитируемый пост)
 Подобные конструкции языка не являются ошибочными

почему не являются? Где это написано?

Это написано в стандарте
12.2 Temporary objects
Цитата

5 The second context is when a reference is bound to a temporary. The temporary to which the reference is bound or
the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the
reference

Автор: mes 17.3.2009, 15:27
Цитата(InvalidProperty @  17.3.2009,  14:11 Найти цитируемый пост)
не забываем, что класс string построен именно таким образом, что его объект не уничтожится, пока на него не закончатся внутренние ссылки. 

Вы про std::string  ? она не обладает подсчетом ссылок и не стоит путать с QString и wxString, которые построены по технологии COW (copy on write)

Цитата(InvalidProperty @  17.3.2009,  14:11 Найти цитируемый пост)
я говорю про тот момент, когда заводится ссылка const string& s = f();)

тут речь идет о случае const int & ri = 13;



Автор: InvalidProperty 17.3.2009, 15:27
самым верным способом будет проверить дизассемблированный текст и, как мне кажется, Lazin говорит правду, ибо компилятор, как только дойдет до строки
Код

const string& s = f();

положит на стек объект, который будет определен возвращаемым функцией значением. Это будет кадр стека внешней функции, поэтому и время жизни - время жизни внешней функции

Автор: mes 17.3.2009, 15:31
Цитата(xvr @  17.3.2009,  14:26 Найти цитируемый пост)
Это написано в стандарте

цитата то обрезана  smile 

Цитата

 is  bound  persists  for the lifetime of the reference or until the end of the scope
  in which the temporary is created, whichever comes first.


только мне кажется эта цитата не объясняет.. ведь в примере по сылке временный объект создается внутри функции и соответсвенно время жизни должно определяться 
scope`ом той функции. 

Автор: GoldFinch 17.3.2009, 15:34
время "жизни" объекта в стеке заканчивается тогда, когда выполняется mov esp,ebp/ret 
данные в стеке непосредственно при этом никуда не пропадают, но при выполнении последующего кода они могут пропасть

Автор: InvalidProperty 17.3.2009, 15:38
Цитата(mes @  17.3.2009,  15:27 Найти цитируемый пост)
Вы про std::string  ? она не обладает подсчетом ссылок и не стоит путать с QString и wxString, которые построены по технологии COW (copy on write)


http://en.wikipedia.org/wiki/String_(C%2B%2B) - обладает. Во всяком случае, я не встречался с примерами, когда не обладает.
Цитата

Although GNU and Dinkumware C++ libraries use reference counting and copy-on-write techniques to avoid unnecessary copying, other implementations might not.


Цитата(mes @  17.3.2009,  15:27 Найти цитируемый пост)
тут речь идет о случае const int & ri = 13

это вообще откуда взялось??? smile 


Автор: vinter 17.3.2009, 15:38
xvr, спасибо. Этого я и ждал(сам не нашел :( ). Очередной идиотизм языка..

Добавлено через 2 минуты и 33 секунды
Цитата

The second context is when a reference is bound to a temporary. The temporary to which the reference is bound or
the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the
reference except as specified below. A temporary bound to a reference member in a constructor’s ctor-initializer (12.6.2)
persists until the constructor exits. A temporary bound to a reference parameter in a function call (5.2.2) persists until
the completion of the full expression containing the call. A temporary bound to the returned value in a function return
statement (6.6.3) persists until the function exits. The destruction of a temporary whose lifetime is not extended by
being bound to a reference is sequenced before the destruction of every temporary which is constructed earlier in the
same full-expression. If the lifetime of two or more temporaries to which references are bound ends at the same point,
these temporaries are destroyed at that point in the reverse order of the completion of their construction. In addition, the
destruction of temporaries bound to references shall take into account the ordering of destruction of objects with static
or automatic storage duration (3.7.1, 3.7.2); that is, if obj1 is an object with the same storage duration as the temporary
and created before the temporary is created the temporary shall be destroyed before obj1 is destroyed; if obj2 is an
object with the same storage duration as the temporary and created after the temporary is created the temporary shall be
destroyed after obj2 is destroyed. [ Example:
Код

struct S {
S();
S(int);
friend S operator+(const S&, const S&);
~S();
};
S obj1;
const S& cr = S(16)+S(23);
S obj2;

the expression C(16)+C(23) creates three temporaries. A first temporary T1 to hold the result of the expression C(16),
a second temporary T2 to hold the result of the expression C(23), and a third temporary T3 to hold the result of the
addition of these two expressions. The temporary T3 is then bound to the reference cr. It is unspecified whether T1 or
T2 is created first. On an implementation where T1 is created before T2, it is guaranteed that T2 is destroyed before T1.
The temporaries T1 and T2 are bound to the reference parameters of operator+; these temporaries are destroyed at the
end of the full expression containing the call to operator+. The temporary T3 bound to the reference cr is destroyed
at the end of cr’s lifetime, that is, at the end of the program. In addition, the order in which T3 is destroyed takes into
account the destruction order of other objects with static storage duration. That is, because obj1 is constructed before
T3, and T3 is constructed before obj2, it is guaranteed that obj2 is destroyed before T3, and that T3 is destroyed before
obj1. —end example ]


Добавлено через 3 минуты и 29 секунд
Цитата(InvalidProperty @  17.3.2009,  16:38 Найти цитируемый пост)
other implementations might not.

это тебе ни о чем не говорит?

Автор: Lazin 17.3.2009, 15:44
Цитата(mes @  17.3.2009,  15:31 Найти цитируемый пост)
только мне кажется эта цитата не объясняет.. ведь в примере по сылке временный объект создается внутри функции и соответсвенно время жизни должно определяться 
scope`ом той функции

нед, там создается временный объект в том-же scop-e что и ссылка на него, объект возвращается по значению

Код

string get()
{
    return string("hello");
}

{
    const string& ref = get();
    ...using ref...
}

как в примере, так делать можно
Код

const string& get()
{
    return string("hello");//wrong
}

...
{
    const string& ref = get();
}

возвращать из ф-ии даже константную ссылку на временный объект нельзя

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

Автор: mes 17.3.2009, 15:47
Цитата(GoldFinch @  17.3.2009,  14:34 Найти цитируемый пост)
данные в стеке непосредственно при этом никуда не пропадают, но при выполнении последующего кода они могут пропасть

не смотря на то что данные присутствуют, они не могут считаться валидными и их присутствиe является лишь особенностью "исполнящей машины."

Добавлено через 2 минуты и 23 секунды
Цитата(Lazin @  17.3.2009,  14:44 Найти цитируемый пост)

нед, там создается временный объект в том-же scop-e что и ссылка на него, объект возвращается по значению

опять невнимательность :(

Автор: xvr 17.3.2009, 15:55
Цитата(mes @ 17.3.2009,  15:31)
Цитата(xvr @  17.3.2009,  14:26 Найти цитируемый пост)
Это написано в стандарте

цитата то обрезана  smile 

Да, там дельше идет речь про 3 исключения из этого правила

Цитата

 is  bound  persists  for the lifetime of the reference or until the end of the scope
  in which the temporary is created, whichever comes first.


Это касается исключений

Цитата

только мне кажется эта цитата не объясняет.. ведь в примере по сылке временный объект создается внутри функции и соответсвенно время жизни должно определяться 
scope`ом той функции.
Угу, только этих объектов 2 
  •  Внутри функции, он разрушается при выходе из функции (но после 2го)
  •  Снаружи, в стеке в месте вызова функции. Инициализируется конструктором копирования (от 1го объекта, который после этого и разрушается), и разрушается когда ссылка, куда его привязали, выходит из области видимости
Ссылка инициализируется адресом 2го объекта

Автор: InvalidProperty 17.3.2009, 15:55
Цитата(vinter @  17.3.2009,  15:38 Найти цитируемый пост)
Цитата(InvalidProperty @  17.3.2009,  16:38 Найти цитируемый пост)
other implementations might not.

это тебе ни о чем не говорит? 


Цитата(InvalidProperty @  17.3.2009,  15:38 Найти цитируемый пост)
Во всяком случае, я не встречался с примерами, когда не обладает.


Зачем нервничать?

Автор: vinter 17.3.2009, 15:57
Цитата(Lazin @  17.3.2009,  16:44 Найти цитируемый пост)
это не идиотизм языка, это нужно для того, что-бы лишний раз не копировать объект передаваемый по значению


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

Добавлено через 3 минуты и 36 секунд
Цитата(InvalidProperty @  17.3.2009,  16:55 Найти цитируемый пост)
Во всяком случае, я не встречался с примерами, когда не обладает.

встречай MSVC 9.0
Код

_Myt& __CLR_OR_THIS_CALL operator=(const _Myt& _Right)
        {    // assign _Right
        return (assign(_Right));
        }

Автор: mes 17.3.2009, 16:02
Цитата(xvr @  17.3.2009,  14:55 Найти цитируемый пост)
Угу, только этих объектов 2 

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

Автор: InvalidProperty 17.3.2009, 16:10
Цитата(vinter @ 17.3.2009,  15:57)
Цитата(InvalidProperty @  17.3.2009,  16:55 Найти цитируемый пост)
Во всяком случае, я не встречался с примерами, когда не обладает.

встречай MSVC 9.0
Код

_Myt& __CLR_OR_THIS_CALL operator=(const _Myt& _Right)
        {    // assign _Right
        return (assign(_Right));
        }

при чем тут это и basic_string?

Автор: vinter 17.3.2009, 16:12
Цитата(InvalidProperty @  17.3.2009,  17:10 Найти цитируемый пост)
при чем тут это и basic_string?

это его метод

Автор: mes 17.3.2009, 16:52
Цитата(InvalidProperty @  17.3.2009,  14:11 Найти цитируемый пост)
(я говорю про тот момент, когда заводится ссылка const string& s = f();

чего то акцент спора сдвинулся в сторону того, имеет ли cow или нет, хотя данный момент не имеет значения, так как подсчет ссылок выполняется во время копии объекта,
а не во время снятия с него ссылки  smile 

Автор: SaDFromSpb 20.3.2009, 02:15
Цитата(vinter @  17.3.2009,  15:57 Найти цитируемый пост)
Lazin, если бы я такое увидил в коде, то посчитал бы ошибкой. До сегодняшнего дня... Т.к все таки ссылка, это ссылка и это как то неправильно, увеличивать время жизни

Господа, мне кажется вы упустили, что речь идет именно о константных ссылках. Только в случае существования константой ссылки время жизни временного объекта продлевается. И об этом написано в статье, на которую ссылается топикстартер. И это будет уже ИМХО более логично, чем оно продлевалось бы при существовании и неконстантных ссылок тоже.

Автор: Lazin 20.3.2009, 06:35
никто ничего не упустил smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)