Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.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++ 如果声明了类型的强制转换运算符和类型的引用,为什么直接列表初始化会导致类型引用强制转换不明确?_C++_Ambiguity_List Initialization_Typecast Operator - Fatal编程技术网

C++ 如果声明了类型的强制转换运算符和类型的引用,为什么直接列表初始化会导致类型引用强制转换不明确?

C++ 如果声明了类型的强制转换运算符和类型的引用,为什么直接列表初始化会导致类型引用强制转换不明确?,c++,ambiguity,list-initialization,typecast-operator,C++,Ambiguity,List Initialization,Typecast Operator,这一问题是在经济衰退的背景下提出的 举个例子: struct foo { int value; operator int&(){ return value; } operator int(){ return value; } }; int main () { int &a(foo{}); // #1 //int &b{foo{}}; // #2 -- ambiguity int &c = foo{}; // #3

这一问题是在经济衰退的背景下提出的

举个例子:

struct foo {
    int value;
    operator int&(){ return value; }
    operator int(){ return value; }
};

int main () {
    int &a(foo{}); // #1
    //int &b{foo{}}; // #2 -- ambiguity
    int &c = foo{}; // #3
    //int &d = {foo{}}; // #4-- ambiguity
    int &d { a }; // #5
    int &e = { a }; // #6
    (void)a;
    (void)c;
    (void)d;
    (void)e;
}

我不明白为什么#2和#4会引起歧义,而#1和#3不会。因此,问题是-如果声明了类型的强制转换运算符和类型的引用,为什么直接列表初始化会导致隐式强制转换引用不明确?

列表初始化用于初始化引用时,将获取列出的值并将其转换为PR值(也称为临时值),它将用于直接初始化引用

所以
int&b{foo{}
在功能上等同于
int&b(int(foo{}))
。这是含糊不清的;它可以通过
操作符int
操作符int&
生成
int

但即使它不是含糊不清的,您仍然会得到一个对prvalue的非常量左值引用。这是违法的。所以这个代码永远不会起作用

大括号初始化列表(大括号)初始化对象,而不是对对象的引用。如果您已经有一个对象,并且希望获得对它的引用,那么不要使用带括号的init列表



但在这种情况下,编译器为什么接受#5

因为列表初始化是一系列具有优先级的规则。一个比我上面指出的优先级更高的规则是一个带括号的init列表,它包含一个值,谁的类型与被初始化的类型相同#5和6正好符合这个要求,因为
d
e
,和
a
都是
int&
s


但是,如果您只是接受我的建议,在不尝试创建对象时不使用带大括号的init列表,那么您就不必担心这样的情况。

int&a(foo{})
是直接初始化
int&b{foo{}
是直接列表初始化。它们不是一回事,因为不是每个人都知道prvalue(比如我自己)。下面是其解释的链接:但在这种情况下,编译器为什么接受#5?它不是类似于
int&d(int(a))?@Nicolas详尽地回答了我的问题!谢谢“带大括号的init列表(大括号)初始化对象,而不是对对象的引用。”,这有点过于简化了。
inta=0没有问题;int&b{a}它初始化引用的地方。@johanneschaub-litb:这是一种简化,是的,但非常有用。它避免了上述情况。