为什么引用不能临时捕获而 const ref 和 rval ref 可以 [英] Why reference can not capture temporary while const ref and rval ref can

查看:57
本文介绍了为什么引用不能临时捕获而 const ref 和 rval ref 可以的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么引用不能捕获临时值而const引用和右值引用可以捕获并延长对象寿命.换句话说,虽然前两行合法,但第三行不合法:

const string &a = string("a");string &&b = string("b");string &c = string("c");//为什么不合法?

解决方案

引用自 N1377

<块引用>

Bjarne 在他的优秀著作《C++ 的设计与演化》中讨论禁止将右值绑定到一个的动机第 3.7 节中的非常量引用.显示了以下示例:

void incr(int& rr) {rr++;}空 g(){双 ss = 1;增加(ss);}

<块引用>

ss 不会增加,因为必须创建一个临时 int 来传递给增量().作者想直接说我们同意这一点分析 100%.霍华德甚至早早被这个虫子"咬了一口编译器.他花了很长时间才追查到底发生了什么(在那如果它是从 float 到 double 创建的隐式转换临时的).

这个理由(不将右值绑定到非常量(左值)引用)从 C++ 诞生之日起一直持续到 C++11(2011).然而,同样的原理不适用于对 const 的左值引用:

将临时文件绑定到对 const 的左值引用是安全的",因为编译器会告诉您是否不小心对该临时文件进行了无用"的修改.

那么为什么将右值绑定到右值引用是安全的"?

再次引用 N1377:

<块引用>

话虽如此,我们想补充一点:你永远不想绑定一个临时到非常量引用......除非你这样做.

非常量引用并不总是作为输出"参数.考虑:

template 类 auto_ptr{上市:auto_ptr(auto_ptr& a);...};

<块引用>

复制"构造函数采用名为a"的非常量引用.但该a"的修改不是这个函数的主要目标.这主要目标是通过窃取a"来构建一个新的 auto_ptr.如果一个"碰巧引用了一个右值,这不是逻辑错误!

总而言之,有时您想修改右值,有时则不想.不同类型的引用允许程序员告诉编译器他们处于哪种情况.

您问题中的绑定是 N1377 激发的绑定的合乎逻辑的结论.

移动语义提案确实致力于提出一个不需要语言更改的解决方案(即引入右值引用).然而,只有库的解决方案并不令人满意,因为用于构建诸如移动构造函数之类的东西的最终语法过于复杂.

Why reference can not capture temporary value while const reference and rvalue reference can capture and prolong object life. In other words while two first lines are legal but third not:

const string &a = string("a");
string &&b = string("b");
string &c = string("c"); // why illegal?

解决方案

Quoting from N1377

Bjarne in his excellent text "The Design and Evolution of C++" discusses the motivation for prohibiting the binding of an rvalue to a non-const reference in section 3.7. The following example is shown:

void incr(int& rr) {rr++;}

void g()
{
    double ss = 1;
    incr(ss);
}

ss is not incremented, as a temporary int must be created to pass to incr(). The authors want to say right up front that we agree with this analysis 100%. Howard was even bitten by this "bug" once with an early compiler. It took him forever to track down what was going on (in that case it was an implicit conversion from float to double that created the temporary).

This rationale (for not binding rvalues to non-const (lvalue) references) held from the dawn of C++, up until C++11 (2011). However the same rationale does not apply to lvalue references to const:

It is "safe" to bind a temporary to an lvalue reference to const because the compiler will tell you if you accidentally make a "useless" modification to this temporary.

So why is it "safe" to bind an rvalue to an rvalue reference?

Again quoting from N1377:

Having said that, we would like to add: You don't ever want to bind a temporary to a non-const reference ... except when you do.

A non-const reference is not always intended to be an "out" parameter. Consider:

template <class T>
class auto_ptr
{
public:
    auto_ptr(auto_ptr& a);
    ...
};

The "copy" constructor takes a non-const reference named "a". But the modification of "a" is not the primary goal of this function. The primary goal is to construct a new auto_ptr by pilfering "a". If "a" happens to refer to an rvalue, this is not a logical error!

In summary, sometimes you want to modify an rvalue, and sometimes you don't. The different types of references allow the programmer to tell the compiler which situation they are in.

The bindings in your question are a logical conclusion of the bindings motivated by N1377.

The move semantics proposal did put effort into coming up with a solution that did not require language changes (i.e. the introduction of the rvalue reference). However library only solutions were unsatisfactory as the resulting syntax for building things like move constructors was overly complex.

这篇关于为什么引用不能临时捕获而 const ref 和 rval ref 可以的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆