Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 隐式转换:常量引用vs非常量引用vs非引用_C++_Reference_Implicit Conversion_Const Reference - Fatal编程技术网

C++ 隐式转换:常量引用vs非常量引用vs非引用

C++ 隐式转换:常量引用vs非常量引用vs非引用,c++,reference,implicit-conversion,const-reference,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); } 我想从

考虑一下这个代码

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);
}

我想从语言规范中了解每种情况的原因、基本原理和参考。当然,函数签名本身并不是不正确的。相反,
A
隐式转换为
B
常量B&
,而不是转换为
B&
,这会导致编译错误。

问题是,从A到B对象的隐式转换会产生一个右值。非常量引用只能绑定到左值

如果B有一个默认构造函数,那么如果将
f(a)
调用更改为
f(B())
,则会得到相同的行为

--

litb为什么是左值提供了一个很好的答案:

--

参考标准解释这些函数调用是如何失败或成功的将是过长的。重要的是如何
B&B=a
常数B&B=a时失败不会失败

(摘自草案n1905)

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

某事物可转换为引用兼容类型的左值的情况

我想从语言规范中了解原因、基本原理和参考

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

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

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
,因此生成了一个临时文件来保存由
ss
初始化的
int
。因此,
incr()


想想看:通过引用调用的整个要点是客户端传递函数更改的内容,在函数返回后,客户端必须能够观察到更改

为什么@Nawaz的问题有23分钟没有得到回答,当我回答时,你比我早30秒给出了答案。真是神奇!哈哈,+1。@Chris:请同时引用相关参考文献,这样我就可以自己探索相关概念。严格来说,你根本不能创建左值或右值,因为值类别是表达式(编译时)的属性,而不是对象(运行时)。@Fred,true。将“转换…创建一个右值”更改为“转换…生成一个右值”,这是我所拥有的标准草案中的术语。答案很好,看到更多解释的引用令人鼓舞。有趣的是:在ARM中,主要表达式的左值的确定如下:“如果标识符为,则结果为左值。”…“如果成员为,则结果为左值。”。我想知道这到底意味着什么,因为它也定义了“左值是指对象或函数的表达式。”。嗯,可能它只是指“如果它指对象或函数,则结果为左值。”。“这很好。我认为它更好地回答了我的问题,因为它解释了为什么它不被允许。我接受这个作为我问题的答案。:-)
void incr(int& rr) { ++rr; }

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