简体   繁体   English

参考的生命周期是否延长?

[英]Is the lifetime of a reference extended?

I'd like to pass a reference into a function. 我想将引用传递给函数。 This code does not work, as I'd expect: 这段代码不起作用,正如我所期望的那样:

struct A {
};

void foo(A& a) {
    // do something with a
}

int main(int, char**) {
    foo(A());
}

I get the compile error 我收到编译错误

invalid initialization of non-const reference of type A& from an rvalue of type A 的类型的非const引用无效初始化A&从类型的一个rvalue A

But when I just add the method A& ref() to A like below and call it before passing it along, it seems I can use a . 但是,当我只是将方法A& ref()A如下所示并在传递它之前调用它,似乎我可以使用a When debugging, the A object is destroyed after foo() is called: 调试时,调用foo()后会销毁A对象:

struct A {
    A& ref() {
        return *this;
    }
};

void foo(A& a) {
    // do something with a
}

int main(int, char**) {
    foo(A().ref());
}

Is this valid code according to the standard? 这个有效的代码是否符合标准? Does calling ref() magically extend the lifetime of the object until foo() returns? 调用ref()神奇地延长对象的生命周期,直到foo()返回?

Your code is perfectly valid. 您的代码完全有效。

In this line 在这一行

foo(A().ref());

The instance of a temporary A lives until the end of the statement ( ; ). 临时A的实例一直存在到语句结尾( ; )。

That's why it's safe to pass A& returned from ref() to foo (as long as foo doesn't store it). 这就是为什么传递A&ref()返回foo (只要foo不存储它)。

ref() by itself does not extend any lifetime, but it helps by returning an lvalue reference. ref()本身不会延长任何生命周期,但它有助于返回左值引用。

What happens in the case of foo(A()); foo(A());的情况下会发生什么foo(A()); ? Here the temporary is passed as an rvalue. 这里临时值作为右值传递。 And in C++ an rvalue does not bind to non-const lvalue references (even in C++11, an rvalue reference does not bind to non-const lvalue references). 在C ++中,rvalue不绑定到非const左值引用(即使在C ++ 11中,rvalue 引用也不绑定到非const左值引用)。

From this Visual C++ blog article about rvalue references : 这篇关于rvalue引用的Visual C ++博客文章中

... C++ doesn't want you to accidentally modify temporaries, but directly calling a non-const member function on a modifiable rvalue is explicit, so it's allowed ... ... C ++不希望你不小心修改临时值,但直接在可修改的右值上调用非const成员函数是显式的,所以它是允许的......

A() creates a temporary object of type A . A()创建一个A类型的临时对象。 The object exists until the end of the full expression in which it is created. 该对象一直存在,直到创建它的完整表达式结束。 The problem in your original code is not the lifetime of this temporary; 原始代码中的问题不是此临时代码的生命周期; it's that the function takes its argument as a non-const reference, and you're not allowed to pass a temporary object as a non-const reference. 这是函数将其参数作为非const引用,并且不允许将临时对象作为非const引用传递。 The simplest change is for foo to take it's argument by const reference, if that's appropriate to what the function does: 最简单的改变是foo通过const引用获取它的参数,如果这适合于函数的作用:

void foo(const A&);
int main() {
    foo(A());
}

There are several questions in this question. 这个问题有几个问题。 I'll attempt to address all of them: 我将尝试解决所有这些问题:


First, you cannot pass a temporary (prvalue) of type A to a function taking A& because non-const lvalue references cannot bind to rvalues. 首先,您不能将A类型的临时(prvalue)传递给采用A&的函数A&因为非const值左侧引用无法绑定到rvalues。 That's a language restriction. 那是一种语言限制。 If you want to be able to pass a temporary, you either need to take a parameter of type A&& or of type A const& - the latter since temporaries can bind to const lvalue references. 如果您希望能够传递临时值,则需要使用类型为A&&或类型为A const& - 后者,因为临时值可以绑定到const左值引用。


Is this valid code according to the standard? 这个有效的代码是否符合标准? Does calling ref() magically extend the lifetime of the object until foo() returns? 调用ref()神奇地延长对象的生命周期,直到foo()返回?

There is no lifetime extension going on in your program at all. 你的程序根本没有进行终身扩展。 From [class.temp]: 来自[class.temp]:

There are three contexts in which temporaries are destroyed at a different point than the end of the full-expression. 有三种情况下,临时表在与完整表达结束时不同的地方被摧毁。 The first context is when a default constructor is called to initialize an element of an array with no corresponding initializer (8.6). 第一个上下文是调用默认构造函数来初始化没有相应初始值设定项的数组元素(8.6)。 The second context is when a copy constructor is called to copy an element of an array while the entire array is copied (5.1.5, 12.8). 第二个上下文是在复制整个数组时调用复制构造函数来复制数组的元素(5.1.5,12.8)。 [...] The third context is when a reference is bound to a temporary. [...]第三个上下文是指引用绑定到临时。

None of those contexts apply. 这些背景都不适用。 We are never binding a reference to a temporary in this code. 我们永远不会在此代码中绑定对临时的引用。 ref() binds *this to an A& , but *this is not a temporary, and then that resulting reference is simply passed into foo() . ref()*this绑定到A& ,但是*this不是临时的,然后将结果引用简单地传递给foo()

Consider this variant of your program: 考虑一下这个程序的变体:

#include <iostream>

struct A {
    A& ref() { return *this; }
    ~A() { std::cout << "~A()\n"; }
};

int main() {
    auto& foo = A().ref();
    std::cout << "----\n";
}

which prints 打印

~A()
----

illustrating that there is no lifetime extension. 说明没有终身延长。


If instead of binding the result of ref() to a reference we instead bound a member: 如果不是将ref()的结果绑定到引用而是绑定成员:

#include <iostream>

struct A {
    A& ref() { return *this; }
    int x;

    ~A() { std::cout << "~A()\n"; }
};

int main() {
    auto&& foo = A().x;
    std::cout << "----\n";
}

then we actually are binding a temporary to a reference and that third context applies - the lifetime of the complete object of the subobject to which the reference is bound is persisted for the lifetime of the reference. 然后我们实际上将临时绑定到引用并且应用第三个上下文 - 引用绑定到的子对象的完整对象的生命周期在引用的生命周期中保持不变。 So this code prints: 所以此代码打印:

----
~A()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 const参考变量的生命周期未延长 - Lifetime of const reference variable not extended xvalue的生命周期是否延伸到引用? - xvalue's lifetime bound to reference extended or not? 当xvalue绑定到const左值引用时,它是否会延长xvalue的生命周期? - Is an xvalue's lifetime extended when it is bound to a const lvalue reference? 临时B()的生命周期是否通过下面的引用int&ri的初始化来扩展? - Does the temporary B() have its lifetime extended by the initialization of the reference int& ri below? 是否在?:expression中创建的C ++临时对象的生命周期是通过将其绑定到本地const引用来扩展的? - Is the lifetime of a C++ temporary object created in ?: expression extended by binding it to a local const reference? 当它被绑定到调用函数中的const引用时,它的返回值的生命周期如何扩展到调用函数的范围? - How is its lifetime of a return value extended to the scope of the calling function when it is bound to a const reference in the calling function? 右值引用的生命周期 - Lifetime of rvalue reference 参考参数寿命 - Reference parameter lifetime 初始化列表中的对象的生存期可以延长吗? - Can lifetime of objects in a initializer list be extended? 从函数返回的对象的延长生命周期 - Extended lifetime of an object returned from function
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM