gpt4 book ai didi

c++ - 为什么我可以 std::move 流右值引用到左值引用?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:07:58 24 4
gpt4 key购买 nike

据我了解 C++11 引用,我不应该能够将右值引用绑定(bind)到(非常量)左值引用,因为前者可能绑定(bind)到临时对象,而后者绝不能绑定(bind)到一个临时的。

但是我发现这种奇怪的行为与临时流对象有关(我尽可能地减少了)

struct Dummy {};
template <typename Stream>
Stream& operator<<(Stream& s, Dummy) {
return s << "."; // <- (A)
}

template <typename Stream>
void pass(Stream&& s) {
std::move(s) << Dummy(); // <- (X) rvalue->lvalue conversion?
}

#include <fstream>
int main() {
pass(std::fstream("test",std::ios::out));
}

如果我写 s << Dummy()在线 (X) , C++ 在 (A) 行提示, 说

error: invalid initialization of reference of type ‘std::basic_fstream<char>&’ from expression of type ‘std::basic_ostream<char>’

但是,为什么代码(如上所示)编译并按预期工作std::move 返回的右值引用应该像表达式 s 一样无法绑定(bind)到左值引用是,但两者都是gcc 4.6.1gcc 4.7.2 react 相同。

为什么这种现象似乎只适用于流?直接传递 Dummy&& 时到一个需要 T& 的函数使用和不使用 std::move 均失败.

最佳答案

basic_ostream过载 operator<<看起来像这样:

template <typename Elem, typename Traits, typename T>
basic_ostream<Elem, Traits>&
operator<<(basic_ostream<Elem, Traits>&& sink, const T& val)
{
return sink << val;
}

这在标准中称为“右值流插入”,位于 §27.7.3.9 [ostream.rvalue]。

它允许从右值 basic_ostream 隐式转换(某种)到一个左值。它是专门为允许 temporary streams to be usable without resorting to tricks 引入的.


至于省略move为什么会编译失败:

Stream& operator<<(Stream& s, Dummy)被称为没有 move ,Stream将是 std::fstream继承自 std::ostream (即 basic_ostream<char> )。

它将使用 basic_ostream<E, T>& operator<<(basic_ostream<E, T>&, const char*)重载以插入您的字符串,然后尝试返回该表达式的结果 ,这将是 ostream 。您不能从 std::ostream& 隐式向下转换至 std::fstream& , 所以你会得到一个错误。

您可以通过返回 s 来解决这个问题在它自己的行上(它不会被隐式地向上转换。)

move 不是问题,因为您通过了我们刚刚首先发现的右值到左值插入运算符。在该函数内部,流是一个 basic_ostream所以Stream也是如此,并且返回类型将匹配。

关于c++ - 为什么我可以 std::move 流右值引用到左值引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14866360/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com