转发就地构造和列表初始化

Lin*_*gxi 1 c++ object-construction language-lawyer c++11 list-initialization

通过转发就地构造,我指的是std :: allocator :: construct和各种emplace方法,例如std :: vector :: emplace_back.我只是发现在C++中转发的就地构造不能(无法?)利用列表初始化语法.结果,似乎人们永远无法就地构建聚合.我只是想确定转发的就地构造是否不支持列表初始化,因此也不支持聚合类型.这是由于语言的限制吗?有人可以提供有关此问题的标准吗?以下是一个例子:

虽然我们可以直接进行就地施工

int(*p)[3] = ...;
new(p) int[3]{1, 2, 3};
Run Code Online (Sandbox Code Playgroud)

我们不能做就地转发就像

std::allocator<int[3]> allo;
allo.construct(p, 1, 2, 3);
Run Code Online (Sandbox Code Playgroud)

Yak*_*ont 5

虽然{}被称为统一初始化语法,但它远非普遍.

拿这两个例子:

size_t a = 3;
size_t b = 1;
std::vector<size_t> v1{a,b};
std::vector<size_t> v2(a,b);
Run Code Online (Sandbox Code Playgroud)

在第一种情况下,我们构造一个包含两个元素的向量,31.

在第二种情况下,我们创建一个包含1,1,1-3个副本的向量1.

实例.

因此,在某些情况下,{}基础构造可能会导致与()基础构造不同的行为.更重要的是,在上面的例子中,没有办法使用{}构造(我知道)达到"3副本1"语法.但是{3,2}可以通过简单地显式创建初始化列表并将其传递给该案例来处理().

由于大多数采用初始化列表的类型可以通过显式传入初始化列表来构建,而C++标准库是为具有构造函数的类型设计的,而不是没有它们的类型,C++标准库几乎统一地使用()和不使用构造{}.

缺点是希望进行列表初始化的类型不能通过此机制进行安装.

理论上,可以将list_emplace构造使用的方法{}添加到每个接口.我鼓励你提出这个建议!

  • "使用{}构造"无法达到"3副本1"语法"是`std :: vector <int> {3,1,std :: allocator <int> {}}`作弊?;) (3认同)
  • @TC我看到了另一个方向(如果括号构造失败,`construct`会回落到列表构造上).这看起来很容易出错:`emplace(1,2)`把'2`和'emplace(1,2,3)`放'1,2,3`似乎完全疯了. (2认同)