c – 为什么直接列表初始化会导致类型引用模糊的模糊,如果转换类型和类型引用被声明?

这个问题在 this answer年的情况下有所上升.

考虑一个例子:

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则不会.所以问题是 – 为什么直接列表初始化会导致隐含的转换参考的歧义,如果转换类型和类型的引用被声明?

解决方法

列表初始化,当用于初始化引用时,将采用列出的值并将其转换为prvalue(aka:a temporary),用于直接初始化引用.

所以int& b {foo {}}在功能上等同于int& b(int(foo {})).哪个是模糊的它可以通过运算符int或运算符int& amp生成该int.

但是即使这不是模糊的,你仍然会得到一个非常量值参考的prvalue.哪个是非法的所以这段代码从来没有工作.

Braced-init-lists(大括号)初始化对象,而不是对对象的引用.如果您已经拥有一个对象并希望获得对象的引用,那么请勿使用braced-init-lists.

But in this case why does compiler accept #5?

因为列表初始化是一系列具有优先级的规则.一个比上面指出的优先级高的规则是一个包含单个值的braced-init-list的情况,它的类型与正在初始化的类型相同. #5和6恰好恰好符合该法案,因为d,e和a都是int& s.

但是,如果您只是采取我的建议,而不是在不尝试创建对象时使用braced-init-list,则不必担心像这样的角色.

相关文章

对象的传值与返回说起函数,就不免要谈谈函数的参数和返回值...
从实现装饰者模式中思考C++指针和引用的选择最近在看...
关于vtordisp知多少?我相信不少人看到这篇文章,多半是来自...
那些陌生的C++关键字学过程序语言的人相信对关键字并...
命令行下的树形打印最近在处理代码分析问题时,需要将代码的...
虚函数与虚继承寻踪封装、继承、多态是面向对象语言的三大特...