const引用延长了临时对象的生命?
曾几何时,我认为这样的代码会失败:
const MyClass& obj = MyClass();
obj.DoSomething();
因为MyClass对象在其全表达式结束时会被销毁,所以将obj留作悬挂引用。 但是,我在这里了解到这不是真的; 该标准实际上有一个特殊的规定,允许const引用使临时对象保持活动状态,直到所有引用被自己销毁。 但是,有人强调,只有const引用才具有这种力量。 今天,我将VS2012中的代码作为实验运行。
struct Foo
{
Foo() { std::cout << "ctor" << std::endl; }
~Foo() { std::cout << "dtor" << std::endl; }
};
void f()
{
Foo& f = Foo();
std::cout << "Hello world" << std::endl;
}
调用f()
时的输出是:
ctor
Hello world
dtor
所以我看了一下C ++ 11草案标准,只发现了这个(§12.2 / 4):
有两种情况下临时销毁在与完整表达式结尾不同的点。 第一个上下文[不适用]。 第二个上下文是当引用绑定到临时的时候。 引用所绑定的临时对象或引用所绑定到的子对象的完整对象的临时对象在引用的生存期内仍然存在。
上面显然缺少了const
这个词。 所以; 有这种行为已经改变了C + + 11,是我错了关于const
事情开始,还是VS2012有一个bug,我只是没有找到相关部分的标准?
行为没有改变,你只需要把你的警告级别提高到/W4
。 VisualStudio的实现甚至非延长使用寿命的规则const
的编译器扩展左值引用。 在此背景下,一个右值绑定到非const
引用行为一样,如果你被绑定到一个const
引用。
用/W4
你会看到这个:
warning C4239: nonstandard extension used : 'initializing' : conversion from 'Foo' to 'Foo &'
1> A non-const reference may only be bound to an lvalue
文本禁止到非右值的结合const
左值参考可以在§8.5.3/ 5中找到
- 否则,引用应该是对非易失性const
类型的左值引用(即,cv1应该是const
),或者引用应该是右值引用。
[例如:
double& rd2 = 2.0; // error: not an lvalue and reference not const
int i = 2;
double& rd3 = i; // error: type mismatch and reference not const
- 例子]
引用声明的后半部分是允许将临时参数与右值参考进行绑定的结果,如litb的答案中所示。
string &&s = string("hello");
这与§12.2/ 5中的生命周期扩展规则相结合,意味着临时生命周期现在将匹配它所绑定的(右值)引用的生命周期。
const
这个词从未出现在本节中。 该规则一直以来(从我记得的时间开始),用于初始化引用的临时文件的生存期延长至与引用的寿命相匹配,而不管引用的类型如何。
有些时候在20世纪80年代后期(非常标准),C ++引入了一个规则,即不能使用临时变量来初始化非const引用。 使用临时初始化非const引用仍然会延长生命周期(推测是),但是因为您无法这样做......大多数编译器实现了一个过渡期,其中这样的初始化只会发出警告(以及生命期被延长)。
出于某种原因,当微软最终决定实施C ++(在90年代初期的某个时候)时,他们决定不实施新规则,并且允许用临时(甚至没有警告)初始化非const引用当其他大多数供应商逐渐将警告转化为错误时)。 当然,执行通常的生命期规则。
最后,在C ++ 11中,引入了新类型的引用,它允许(或甚至需要)使用临时的初始化。 尽管如此,关于临时性人生的规则并没有改变。 用于初始化引用(不论引用类型如何)的临时文件的生存期延长。
(除了少数例外:我不建议在初始化列表中使用临时初始化类成员引用。)
不,因为右值引用不需要是const
,所以标准报价是正确的
string &&s = string("hello");
终身仍在扩大。 使非代码非参数的代码无效的约束是在第8节(请注意,它不是在引用的段落中添加“const”和“rvalue reference”等的正确位置,您需要主动拒绝这样的绑定,不仅仅是说这样的绑定的生命周期不会扩大,因为你会保持绑定本身的格式不变)。
链接地址: http://www.djcxy.com/p/20775.html