3

这有效:

class Foo {};
void external_function(Foo&);
void f() {
  Foo b;                                                                                                                                         
  external_function(b);                                                                                                                          
}

这不会:

class Foo {};
void external_function(Foo&);
void f() {
  external_function(Foo());
}

铿锵声 说:

aac.cc:3:6: note: candidate function not viable: no known conversion from 'Derived' to 'Base &' for 1st argument;

GCC 实际上在以下方面更有帮助:

aac.cc:7:30: error: invalid initialisation of non-const reference of type ‘Base&’ from an rvalue of type ‘Derived’

Herb Sutter ( http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/ ) 说非常量引用不能用于右值,这在他的例子中是有道理的,但在我的例子中没有,因为对象在 external_function() 调用期间存在,不是吗?

我知道如何让它发挥作用;只需创建一个命名对象,使其不是右值(就像我在上面所做的那样),或者使用 const ref。但我想知道为什么不允许这样做,因为这对我来说似乎是安全的。

4

3 回答 3

9

您不能将任何类型的临时绑定到非常量左值引用。这里的继承只是一种干扰。

struct Foo{};

void bar(Foo&) {}
void cbar(const Foo&) {}

int main()
{
  Foo f;
  bar(f);      // OK
  bar(Foo());  // ERROR
  cbar(Foo()); // OK: const reference binds to temporary
}

至于终极的“为什么?” ,它只是被认为容易出错,允许通过左值引用修改右值。引自“ C++ 编程语言,第四版”§7.7.1

对变量的引用和对常量的引用是有区别的,因为为变量引入临时变量很容易出错;对变量的赋值将成为对 - 即将消失 - 临时的赋值。对常量的引用不存在这样的问题......

于 2013-08-15T10:20:35.307 回答
1

“为什么”是为了避免难以检测的错误。如果参数不是 const,则意味着该函数正计划更改它(否则只需将其设为 const!)更改临时对象不太可能是您想要的,并且通常是一个非常难以弄清楚的错误。

于 2013-08-15T20:45:03.023 回答
0

因为标准是这样说的,因为他们认为这可能会导致错误(我不同意)。没有技术原因不允许这样做。

于 2013-08-19T12:18:46.977 回答