为何左值可传入接受Square&右值引用的foo类构造函数?
为什么传入左值却能匹配接受右值引用的构造函数?
嘿,这个问题的核心其实是C++里的引用折叠规则,还有你用typedef定义引用别名带来的小“陷阱”。
先拆解一下你的代码:你在foo类里把Square&typedef成了sqref,然后构造函数的参数写成了sqref && _ref。这里可不能直接把它当成Square&的右值引用来看——因为C++里有个引用折叠的规则:
- 当你组合两种引用类型时(比如左值引用+右值引用),只要其中一个是左值引用,最终的类型就会折叠成左值引用。简单说就是
T& &&会变成T&,反过来T&& &也一样。
所以你的构造函数参数sqref &&展开后其实是Square& &&,经过引用折叠就变成了Square&——也就是一个普通的左值引用!这就难怪你传入左值s的时候完全没问题,因为构造函数本质上就是在接受一个左值引用。
你可以自己验证一下:如果把sqref换成const Square&的别名sqcref,那构造函数参数sqcref &&会折叠成const Square&,同样能接受左值。
要注意的是,这种引用折叠只在通过typedef、模板参数这类间接方式定义引用的时候才会生效。要是你直接写foo(Square& && _ref),编译器肯定会报错,因为C++不允许直接声明“引用的引用”,但通过别名或者模板的方式就会触发这个折叠规则。
再看你的运行结果,构造函数里把s.str置为0,第二次打印s的时候是空字符串,这也完全符合左值引用的行为——我们直接修改了原对象的成员嘛。
内容的提问来源于stack exchange,提问作者Rollie
相关产品推荐
相关产品推荐

