c++ - 什么时候不能将对象转换为引用?

标签 c++ gcc reference

我想从 http://code.google.com/p/enhsim 编译以下代码行:

enh::eout << enh::setw(26);

gcc 给出以下错误:

error: no match for 'operator<<' in 'enh::eout << enh::setw(26)'

但是 EnhSimOutput 类(enh::eout 是一个实例)确实声明:

EnhSimOutput& operator<< (setw& p);

如果我实现一个按值接受对象的操作版本,这个问题就会消失:

EnhSimOutput& operator<< (setw p);

或者如果我将 enh::setw 对象创建为本地对象,即:

enh::setw wValue(26);
enh::eout << wValue;

我的问题是:为什么 gcc 不选择运算符的“按引用”版本开始?

编写这段代码的开发人员显然可以编译它,但默认的 gcc 拒绝这样做。为什么单独声明为局部变量的对象与局部创建的内联对象有区别?

最佳答案

enh::setw(26); 是一个 rvalue 。实际上,像这样的临时变量是右值。右值具有特殊属性。其中之一是它们的地址不能被获取(&enh::setw(26); 是非法的),并且它们通常不能绑定(bind)到对非常量的引用(一些临时可以绑定(bind)到对非常量的引用,但这些遵循特殊规则:在临时对象上调用成员函数并通过对非常量的引用捕获异常对象。在后一种情况下,临时偶数是一个左值)。

有两种表达式:lvalues 表示对象(反过来可以存储值)或函数,rvalues 表示读出的值对象的或由临时值、数字文字和枚举器常量表示的。在 C++03 中,为了能够将这样的值传递给通过引用接受其值的函数,有一条规则可以通过 reference-to-const 接受它们:setw const& p会接受的。也就是说,您必须像这样声明您的运算符(operator):

EnhSimOutput& operator<< (setw const& p);

这有点不幸,因为您无法区分常量左值(例如,您使用 const enh::setw e(26); 在堆栈上创建的对象)和非 const 或 const右值(如 enh::setw(26); 是一个非常量临时值)。另外,如果你这样做,参数不能在其上调用非常量成员函数,因为它是对常量的引用。因此,下一个 C++ 版本 C++1x 引入了一种新的引用,即所谓的右值引用,它解决了这个问题。


Microsoft Visual C++ 编译器将右值绑定(bind)到对非常量的引用,但在执行此操作时会发出警告(您必须至少使用警告级别 4 才能显示)。这很不幸,因为在移植到其他标准合规性更严格的编译器时会出现问题。

关于c++ - 什么时候不能将对象转换为引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/445570/

相关文章:

c++ - 将 uint64_t 位掩码转换为 std::array of bool

perl - 理解我脚本中指向散列的 Perl 指针

c++ - 函数应该返回引用还是对象?

delphi - Delphi简单数据类型等效

c++ - 我怎样才能停止让其他困惑/扩展我的命名空间?

c++ - 什么是指针引用?

c - 误导性信息

ios - Xcode 5 llvm-g++ 和 llvm-gcc 路径?

c++ - 计算数组中的反转次数

c# - 将 C++ 数组返回到 C#