{object}的类型是什么?

时间:2016-11-24 10:43:36

标签: c++

请考虑以下代码:

void foo (M&) {}

M m;
foo ({m});

因此,表达式{m}被视为右值引用,这就是此代码无法编译的原因。

{object}是否总是生成临时对象,这是真的吗?

如果不是,那么如何确定它何时发生? 如果是,请考虑以下代码:

struct M {};

struct I {
    I (M&) {}
};

struct MM {
    MM (M& p)
    : m (p), i ( {p} )
    {}

    M& m;
    I i;
};

M m;
MM mm {m};

这里完全没有问题,那么第一个示例中的{m}与第二个示例中的{p}之间有什么区别?

编译器(GCC 4.8.1)结果(第一个例子):

main.cpp:366:13: error: invalid initialization of non-const reference of type ‘M&’ from an rvalue of type ‘<brace-enclosed initializer list>’
     foo ({m});
             ^
main.cpp:359:6: error: in passing argument 1 of ‘void foo(M&)’
 void foo (M&) {}

2 个答案:

答案 0 :(得分:2)

  

{object}的类型是什么?

这取决于具体情况。在某些情况下,例如在构建具有std::initializer_list参数的类型时,它将属于std::initializer_list<decltype(object)>类型。在其他情况下,它将用于初始化聚合或其他类型的成员,在这种情况下,句法形式{object}不会 类型本身

  

{object}总是生成临时对象,这是真的吗?

不,在你的情况下,它不应该。这是a bug in the C++11 spec与指定列表初始化的子句的排序有关。旧的措辞意味着您的调用导致构造临时(由于非const引用参数而形成不良),但在新规则下,引用绑定到单个初始化列表元素。您的旧编译器实现旧的措辞,而newer compilers实现固定的行为。

  

这里完全没有问题,那么第一个例子的{m}和第二个例子的{p}有什么区别呢?

不同之处在于{m}用于初始化M的{​​{1}}参数(旧措辞无效),但foo初始化{p}会员。因此,I被视为p构造函数的参数,绑定到I参数,并且由于M&是左值,所以一切都很好,花花公子。 / p>

答案 1 :(得分:0)

  

{object}总是生成临时对象吗?

否(继续阅读)。

两个片段都有效(您应该使用最新的编译器)并且将成功编译。

{p}案件属于[over.match.list]/p1

  

当非聚合类类型T的对象被列表初始化,使得[dcl.init.list]指定根据本节中的规则执行重载解析时,重载决策分两个阶段选择构造函数:

     

(1.1)   最初,候选函数是类T的初始化列表构造函数([dcl.init.list]),参数列表由初始化列表作为单个参数组成。

     

<强>(1.2)   如果找不到可行的初始化列表构造函数,则再次执行重载解析,其中候选函数是类T的所有构造函数,参数列表由初始化列表的元素组成。

具体在(1.2)中,而{m}是另一种情况的列表初始化。