Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ *非*常量引用会延长临时人员的寿命吗?_C++_Visual Studio 2012_C++11_Language Lawyer - Fatal编程技术网

C++ *非*常量引用会延长临时人员的寿命吗?

C++ *非*常量引用会延长临时人员的寿命吗?,c++,visual-studio-2012,c++11,language-lawyer,C++,Visual Studio 2012,C++11,Language Lawyer,曾几何时,我假设这样的代码会失败: const MyClass& obj = MyClass(); obj.DoSomething(); 因为MyClass对象将在其完整表达式结束时被销毁,留下obj作为悬空引用。然而,我(在这里)知道这不是真的;该标准实际上有一个特殊的规定,允许常量引用保持临时性,直到所述引用本身被销毁。但是,有人强调,只有常量引用具有这种能力。今天,我在VS2012中运行了下面的代码作为实验 struct Foo { Foo() { std::cout &

曾几何时,我假设这样的代码会失败:

const MyClass& obj = MyClass();
obj.DoSomething();
因为MyClass对象将在其完整表达式结束时被销毁,留下obj作为悬空引用。然而,我(在这里)知道这不是真的;该标准实际上有一个特殊的规定,允许常量引用保持临时性,直到所述引用本身被销毁。但是,有人强调,只有常量引用具有这种能力。今天,我在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;
}
因此,我查看了C++11标准草案,只发现了以下内容(§12.2/4):

有两种情况下,临时机构会在同一时间被销毁 与完整表达式的结尾不同的点。第一个上下文[没有] 应用]。第二个上下文是引用绑定到 暂时的。引用绑定到的临时文件或 临时对象,它是子对象的完整对象 引用被绑定在引用的生存期内


上面明显没有const一词。所以对于C++11,这种行为是否已更改,是我一开始对
常量的理解有误,还是VS2012有一个bug,而我只是没有找到标准的相关部分?

这种行为没有更改,您只需要将警告级别提高到
/W4
。VisualStudio甚至将非
const
lvalue引用作为编译器扩展来实现生存期扩展规则。在此上下文中,将右值绑定到非
常量
引用的行为与将右值绑定到
常量
引用的行为相同

使用
/W4
可以看到:

warning C4239: nonstandard extension used : 'initializing' : conversion from 'Foo' to 'Foo &'
1>  A non-const reference may only be bound to an lvalue
在§8.5.3/5中可以找到禁止将右值绑定到非
常量左值引用的文本

-否则,该引用应为对非易失性常数的左值引用(即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
-[结束示例]

引用语句的后半部分允许将临时引用绑定到右值引用,如中所示


这与§12.2/5中的生存期延长规则相结合,意味着临时文件的生存期现在将与其绑定的(右值)引用的生存期相匹配。

否,因为右值引用不需要是
常量,因此标准引用是正确的

string &&s = string("hello");

寿命仍在延长。使代码对非常量左值引用无效的约束条件见第8条(请注意,仅添加“常量”和“右值引用”并不合适)在你引用的段落中,你需要主动拒绝这种绑定,而不仅仅是说这种绑定的生存期没有延长,因为你会让绑定本身保持良好的格式)

本节中从未出现过
const
一词。规则 从我记事起就一直是这样 用于初始化引用的临时变量有其生存期 扩展以匹配引用的类型,而不考虑类型 参考文献的一部分

1980年底的某个时候(非常标准),C++介绍 无法使用临时文件进行初始化的规则 非常量引用。使用初始化非常量引用 一个临时文件仍然会延长生命周期(大概是这样),但是 既然你做不到。。。大多数编译器都实现了 一个过渡期,在此期间,这样的初始化只会 发出警告(生命周期已延长)

由于某种原因,当微软最终决定实施 C++(1990年初的某个时候),他们决定不 实现新规则,并允许初始化 带有临时(甚至没有警告)的非常量引用, 在大多数其他供应商逐渐转向 警告变成错误)。当然,政府实施了 通常的寿命规则

最后,在C++11中,引入了新的引用类型, 允许(甚至要求)使用 临时的。关于临时工寿命的规定还没有出台 但是改变了;用于初始化的临时文件 引用(无论引用的类型如何)具有 寿命延长

(除了少数例外:我不建议使用临时 在初始化中初始化类成员引用的步骤

允许您将右值绑定到非常量左值引用这一事实本身就是一个扩展。@布赖恩,我不是这么说的吗?@Praetorian,我确实是这么说的。因此,“仅常量引用延长生存期”规则是其他一些规则的副作用,这些规则指出,只有常量引用才能绑定到右值?@dlf最终找到了您要查找的文本,请参阅更新answer@dlf从来没有“只有常量引用才能延长生存期”的规则。早在禁止使用临时变量初始化非常量引用的规则出台之前,生命周期的延长就应用于所有引用。这个问题实际上提出了三个链接在一起的是非问题。我不清楚你对哪一个回答不。还是你对这三个问题都给出了相同的答案?你能详细说明最后一段关于会员推荐信的内容吗?无论如何,我从未想过要这样做,但我对你的确切推理很感兴趣。@ChristianHackl用于初始化成员引用的临时变量的生存期不会延长到引用的生存期;它的生命周期在构造函数结束时结束(这将导致一个悬空引用)。感谢您的澄清。我本可以凭直觉猜到,但很高兴得到证实。仍然让我想知道为什么这样的事情一开始就不需要编译器诊断。
string &&s = string("hello");
string &&s = string("hello");