Re: [问题] reference vs lifetime of a temporary object

楼主: Caesar08 (Caesar)   2016-09-29 21:06:01
※ 引述《klsdf (静雨澪)》之铭言:
: 标题: [问题] 右值参照问题
: 时间: Wed Sep 28 21:20:59 2016
本文主要是讲lifetime of a temporary object,所以把回文的标题改了
我在你的内文说到"reference不管是lvalue reference还是rvalue reference"
"都不会延长被reference的object的生命周期"
其实这是错误的(抱歉,我误导你了 <(_ _)> )
然后板上又没有相关的资料(查temporary/暂时/生命/lifetime),所以就写这篇文章
另外,先说一件跟本文章没关系的事情
以我的经验,C++ 3大compiler(GCC、Clang、MSVC)
MSVC(也就是VC++)是最不符合C++标准的
也就是你的code明明可以通过MSVC的compile,却不能通过GCC与Clang的compile
让你以为GCC跟Clang怎么那么烂
但实际的情况是MSVC本身有问题,GCC跟Clang才是尽可能符合C++标准的
所以如果当你的code没办法通过GCC与Clang的compile,别怀疑,是你的code有问题
正文开始:
实际上,reference(如果没有特别说明,下文的reference都包含lvalue reference与
rvalue reference,把reference to const改成rvalue reference也可以)
是会延长temporary object的lifetime的,除了3种情况
先讲一下什么是延长lifetime,如果写
int test(){
return 10;
}
int main(){
const int &i=test();
//...
cout<<i<<endl;
}
原本在const int &i=test()结束,会destroy temporary object的动作,被挪到
i的lifetime结束才执行,所以cout会正确无误地,把10印出去
这种情况,就是temporary object的lifetime被延长了
但是呢,并不是所有reference都能延长temporary object,例如(其中1种例外情况)
string get(){
return "abc";
}
struct Test{
const string &str; //oops, dangling reference
Test(const string &a)
:str{a}{}
};
int main(){
Test test(get());
}
那当test(get())结束时,Test::Test的parameter a所reference的object就被destroy了
也就是说,test里面的str,就会是一个dangling reference
可能有人会问为什么
"test.str reference a,a又reference get()的return value"
"所以get()的return value(temporary object)被a延长,a又被str延长,不行吗?"
答案是不行
因为虽然Test::Test的parameter是reference,但
延长temporary object lifetime的规则,在"function的pararmeter是reference时"无效
所以test.str真的会是一个dangling reference
最后,讲那么多,还是要来回答你原本的问题
: 但就我的认知如果是直接用const auto& =test() 去接了话
: 可以活在do while一个round里(用VC run的结果是这样)
: 但用DerivedRef接看起来是下一行就结束周期
: 这就是我不了解的地方
因为现在用const auto &a=test(),所以test()的return value(temporary object)
的确被a延长了
所以在while结束的时候,temporary object才会被destroy
但是,DerivedRef的案例不一样
首先,你的Any template(http://codepad.org/XT2ed7Hc)的assignment operator
并没有test这个class type,有的只是 operator=(const Any& a)与operator=(Any&& a)
也就是说,在你的code(http://codepad.org/CZhy27AQ)40行
"any = test();"
test()产生的temporary object,需要先转成Any这个class type
他会先呼叫template<typename U>Any(U&& value)这个constructor
然后此时的value虽然是reference,但是他是延长temporary object的例外情况
所以当any = test()执行结束后,ptr->value就是一个dangling reference
: → firose: DerivedRef 就算被 const T& 也不能活超过 do-block 09/29 12:4
: → firose: 说错, 是 test(), 只是这里问题是它能活多久? 09/29 12:4
它只能活到any = test()这个expression结束
: 我的疑问是它太早死了QQ
它没有太早死,它死的时机刚刚好
注:
在文章一开头有说到MSVC不符合C++标准的问题,现在这里就是了
在(http://codepad.org/XT2ed7Hc)里struct DerivedRef的T& value这种写法
在遇到any = test()就会出错,因为你用lvalue reference reference rvalue reference
这段code拿去给GCC跟Clang compile,会发现他们两个都跟你说compile失败
不是GCC跟Clang有问题,真正有问题的是MSVC
作者: pttworld (批踢踢世界)   2016-09-29 21:42:00
yoco
作者: Feis (永远睡不着 @@)   2016-09-29 23:33:00
...
作者: CoNsTaR ((const *))   2016-09-30 07:13:00
作者: klsdf (静雨澪)   2016-09-30 08:43:00
感谢Caesar大的解释,我昨天下班的时候有看你贴的连结我看完的那时候的理解是原本test()诞生时是rvalue被const auto & = test()后成为具名的rvalue 就是lvalue所以会等const auto &的scope结束后才会delete而我的DerivedRef内的const T&把test()rvalue ref进来时并没有被Compiler辨识出为具名的rvalue,我原本也是理解因为是函数呼叫关系导致Compiler无法推导出它是具名rvalue经由这篇文章我可以理解为什么了,谢谢Caesar大。
作者: bluesoul (忙死你老爸)   2016-09-30 11:41:00
好文

Links booklink

Contact Us: admin [ a t ] ucptt.com