隐式转换:const引用vs非const引用vs非引用

时间:2011-01-16 08:09:17

标签: c++ reference implicit-conversion const-reference

考虑这段代码,

struct A {};
struct B {  B(const A&) {} };
void f(B)
{
    cout << "f()"<<endl;
}
void g(A &a)
{
    cout << "g()" <<endl;
    f(a); //a is implicitly converted into B.
}
int main()
{
    A a;
    g(a);
}

这个compiles fine,运行正常。但是,如果我将f(B)更改为f(B&),则doesn't compile。如果我写f(const B&),它再次compiles fine,运行正常。原因和理由是什么?

要点:

void f(B);         //okay
void f(B&);        //error
void f(const B&);  //okay

我希望听到语言规范中的原因,基本原理和参考资料。当然,功能签名本身并不正确。相反,A隐式转换为Bconst B&,但不转换为B&,这会导致编译错误。

2 个答案:

答案 0 :(得分:7)

  

我想听听语言规范中的原因,理由和参考资料

C ++的设计和演变是否足够?

  但是,我犯了一个严重的错误,允许非const引用由非左值初始化[由我发表评论:措辞不精确!]。例如:

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

void g()
{
    double ss = 1;
    incr(ss);    // note: double passed, int expected
                 // (fixed: error in release 2.0)
}
     

由于类型不同,int&无法引用传递的double,因此会生成一个临时值来保存int初始化ss的值。因此,incr()修改了临时,结果未反映回调用函数 [强调我的]。

考虑一下:引用调用的全部内容是客户端传递函数更改的内容,在函数返回后,客户端必须能够观察到更改

答案 1 :(得分:4)

问题是从a到B对象的隐式转换产生rvalue。非const引用只能绑定到左值。

如果B有默认构造函数,如果将f(a)调用更改为f(B()),则会产生相同的行为。

-

litb为左值提供了一个很好的答案:Stack Overflow - often used seldom defined terms: lvalue

GotW #88: A Candidate For the “Most Important const”

Stack Overflow - How come a non-const reference cannot bind to a temporary object?

-

通过引用标准来解释这些函数调用失败或成功的时间过长。重要的是B& b = a;失败,而const B& b = a;没有失败。

(来自草案n1905)

  

类型“cv1 T1”的引用由类型“cv2 T2”的表达式初始化,如下所示:
     - [是左值并且参考兼容或可隐式转换为参考兼容类型的左值... ]
     - 否则,引用应为非易失性const类型(即,cv1应为const)。

Here's可以将某些内容转换为参考兼容类型左值的情况。