C++ 使用*non*-const引用参数的函数在参数列表中创建的临时变量的生存期是否包含函数调用?
我已经习惯了这样一个事实,即const引用会延长临时引用的生命周期,直到引用超出范围:C++ 使用*non*-const引用参数的函数在参数列表中创建的临时变量的生存期是否包含函数调用?,c++,reference,C++,Reference,我已经习惯了这样一个事实,即const引用会延长临时引用的生命周期,直到引用超出范围: class X {}; { X const & x = X(); // Lifetime of x extended to the end of the scope // in which x is declared because it was declared // as a *const* reference } 。。。我也知道一个临时的会一直存在到它被创建
class X {};
{
X const & x = X();
// Lifetime of x extended to the end of the scope
// in which x is declared because it was declared
// as a *const* reference
}
。。。我也知道一个临时的会一直存在到它被创建的表达式结束:
// Contrived example to make a point about lifetime of a temporary in an expression
class Y
{
public:
Y() : y(5) {}
Y & operator+=(int const & rhs)
{
y += rhs;
return *this;
}
int foo() { return y; }
private:
int y;
};
// n in the following line of code is 11 and the code is valid
// - the lifetime of the temporary persists to the end of the expression
int n = (Y() += 6).foo();
假设我对上述两项都是正确的,我怀疑在函数参数列表中创建的临时变量将在函数调用的生存期内保持不变,即使它绑定到非-const引用:
class X {};
void foo(X & x)
{
// x is valid in this function,
// even though the parameter is declared
// as a *non*-const reference - correct?
}
// Valid, I think, even though the function parameter
// is declared as a **non**-const reference
// - because the lifetime of the temporary persists until the expression
// is fully evaluated - right?
foo(X());
我认为我的经验和理解是正确的——将函数参数列表中创建的临时变量绑定到非-const引用参数是安全的
但我想确认一下我是对的,因为我在任何地方都找不到这个问题的明确答案
谢谢 你肯定是对的
标准:
12.2临时对象[类别临时]
[……]
有两种情况下,临时词语在与完整表达结尾不同的位置被销毁。第一个上下文是调用默认构造函数初始化数组的元素时。如果 构造函数有一个或多个默认参数,即销毁在默认值中创建的每个临时参数 参数在构造下一个数组元素(如果有)之前排序。
第二个上下文是将引用绑定到临时上下文。引用绑定到的临时对象或作为引用绑定到的子对象的完整对象的临时对象在引用的生存期内持续存在,除了:
-构造函数的ctor初始值设定项(12.6.2)中与引用成员的临时绑定将持续存在,直到构造函数退出。
-在函数调用(5.2.2)中临时绑定到引用参数的操作会一直持续到包含该调用的完整表达式完成为止。
-函数返回语句(6.6.3)中返回值的临时绑定的生存期没有延长;在return语句的完整表达式末尾销毁临时表达式。
-与新初始值设定项(5.3.4)中引用的临时绑定持续存在,直到完成 包含新初始值设定项的完整表达式
要使用更高级别的构造函数和存储引用的对象再次提问吗?重复数据消除程序给出了语言律师的答案,下面是实现细节的答案: 如果通过引用传递任何对象,则实际上是在传递指向该对象的指针。由于调用者只传递指向对象的指针,因此通过引用传递的对象必须由调用者构造 另一方面,被调用方只能看到传入的指针。它看不到调用方如何构造其指针被传递的对象。此对象可以是临时对象(仅在
常量
引用的情况下,因为临时对象不能作为非常量引用传递),也可以是具有函数作用域的变量,它可以是调用者已经传递给调用者的对象,甚至可以是分配了新
的对象。因此,它不能破坏对象,因为它不知道如何破坏
因此,在被调用者将控制权返回给调用者之后,由调用者来清理临时文件-通过引用传入的任何内容都必须在被调用者的整个运行时中有效
请注意,整个参数完全不知道引用是否为常量。对非常量的引用不绑定到临时变量。你的问题没有意义。@jrok:他们在使用MSVC时会这样。
+
对+=
@MichaelBurr来说真是个坏名字。我想在这里假设一个隐式的“在标准C++中”是安全的。啊-这就解释了。我正在使用MSVC。。。我想确认这个行为,显然这是一件好事,因为现在我知道它是无效的。奇怪的是,它没有说任何关于const
。我认为在声明引用时通常需要const
来延长临时引用的生存期。@DanNissenbaum:Automatic/staticconst
引用将生存期延长到完整语句之外,这里是关于标准生存期的。第二个上下文是引用绑定到临时引用时的上下文。引用绑定到的临时对象或作为引用绑定到的子对象的完整对象的临时对象在引用的整个生命周期内持续存在
(摘自答案中的引文),对我来说,这意味着临时变量的生存期超出了声明临时变量的完整表达式。@DanNissenbaum:永远不要忘记异常列表。X&X=X()
似乎不是例外,但它并没有说const
是必需的,我认为这是必需的。现在我很困惑,因为在你的回答中你说它是合法的(这对我来说很有意义),但在问题下面的评论中,@jrok和其他人说它是非法的。我遗漏了什么?事实上,我从来没有想过,在我的回答中,将临时引用作为非常量引用是否合法。当然,评论员们是对的,临时引用不能作为非常量引用传递。但是,这只考虑了一种可能的调用场景,它对参数本身没有任何影响。我会尽量澄清一些事情。