当我将{}分配给已经存在的对象时,这意味着什么?

时间:2016-10-20 23:57:22

标签: c++ c++11 grammar

#include <vector>
#include <queue>
using namespace std;
int main()
{
    vector<priority_queue<int>> vec;
    vec.push_back({});//compiles
    vec.push_back({1});//don't work 
    vec[0] = {};//compiles
    vec[0] = {1};//don't work 
    return 0;
}

priority_queue没有初始化列表构造函数。

但我仍然可以为其指定一个{}。

我认为这意味着我只使用默认构造函数构造了一个空的priority_queue,并将其分配给已经存在的priority_queue对象。

但不应该是这样的吗?

vec[0] = priority_queue<int>{};//compiles
vec[0] = priority_queue<int>();//compiles

这意味着什么?为什么它有效? 我刚刚省略了priority_queue部分。

vec[0] = {};//compiles
vec[0] = ();//don't work 

这并不意味着我可以随时重新初始化我的队列对象吗?

priority_queue<int> que{};
que = {};//compiles
que{};//don't work

这里有{}类似于nullptr吗?

{}是一个空对象,像nullptr是每种指针的空指针?

priority_queue<int>* p{};
p = nullptr;
p = {};// still works

2 个答案:

答案 0 :(得分:4)

赋值运算符(包括复合赋值)在C ++ 11中得到了特殊处理,因为它包含在允许发生列表初始化的上下文列表中。由于这种特殊处理,在赋值运算符的右侧允许使用普通{ ... }初始值设定项,如在

vec[0] = {};

并且,根据赋值运算符的规范,它被解释为

vec[0].operator =({});

在这种情况下,{}用作函数调用中参数的初始值设定项。由于初始化的对象不是聚合,因此{}的内容被解释为常规构造函数的参数列表。由于列表为空,因此会导致选择默认构造函数。

此特殊处理不会扩展到其他运营商

struct S
{
  S(int, int, int) {}
  S &operator +=(const S& rhs) { return *this; }
  S operator +(const S& rhs) const { return *this; }
};

int main()
{
  S s(1, 2, 3);
  s = { 4, 5, 6 };  // OK - special treatment for `=`
  s += { 4, 5, 6 }; // OK - special treatment for `+=`
  s + { 4, 5, 6 };  // Error - no special treatment for `+`
  s + S{ 4, 5, 6 }; // OK, constructing the object explicitly works
}

答案 1 :(得分:2)

大括号({})通常用于初始化对象,而不仅仅是初始化列表。因此,没有初始化列表的类仍然可以使用大括号来初始化对象,例如

class A { 
    public: 
    A(int i);
}

A a{5}; // Invokes A's constructor

它也可以用于aggregate initialization(例如,初始化结构数据成员。)在您的情况下,它调用priority_queue的默认构造函数。