当我将 {} 分配给一个已经存在的对象时,这意味着什么?
What does it mean when I assign {} to an already exsiting object?
#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
大括号 ({}
) 通常用于对象的初始化,而不仅仅是初始化列表。因此,没有初始化列表的 class 仍然可以使用大括号来初始化对象,例如
class A {
public:
A(int i);
}
A a{5}; // Invokes A's constructor
它也可以用于 aggregate initialization(例如结构数据成员的初始化。)在你的例子中,它调用了 priority_queue
的默认构造函数。
赋值运算符(包括复合赋值)在 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
}
#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
大括号 ({}
) 通常用于对象的初始化,而不仅仅是初始化列表。因此,没有初始化列表的 class 仍然可以使用大括号来初始化对象,例如
class A {
public:
A(int i);
}
A a{5}; // Invokes A's constructor
它也可以用于 aggregate initialization(例如结构数据成员的初始化。)在你的例子中,它调用了 priority_queue
的默认构造函数。
赋值运算符(包括复合赋值)在 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
}