什么时候聚合初始化在C ++ 11中有效? [英] When is aggregate initialisation valid in C++11?

查看:216
本文介绍了什么时候聚合初始化在C ++ 11中有效?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有以下代码:

#include <iostream>
#include <string>

struct A
{
  A() {}
  A(const A&) { std::cout << "Copy" << std::endl; }
  A(A&&) { std::cout << "Move" << std::endl; }
  std::string s;
};

struct B
{
  A a;
};

int main()
{
  B{A()};
}

这里,我相信struct A 不是一个聚合,因为它有两个非平凡的构造函数和一个 std :: string 成员,我假定不是一个聚合。这可能意味着 B 也不是一个聚合。

Here, I believe struct A is not an aggregate, as it has both non-trivial constructors and also a std::string member which I presume is not an aggregate. This presumably means that B is also not an aggregate.

但我可以聚合初始化B.此外,无需调用复制或移动构造函数(例如, ideone 上的C ++ 0x GCC 4.5.1)。

Yet I can aggregate initialize B. In addition this can be done without either the copy nor move constructor being called (e.g. C++0x GCC 4.5.1 on ideone).

这种行为似乎是一个有用的优化,特别是对于没有廉价移动的大型堆栈类型。

This behavior seems like a useful optimization, particularly for composing together large stack types that don't have cheap moves.

我的问题是:这种聚合初始化在C ++ 0x下有效吗?

My question is: When is this sort of aggregate initialization valid under C++0x?

修改+跟进问题:

DeadMG回答如下:

DeadMG below answered with the following:


这不是聚合初始化,它是统一的初始化,这基本上是在调用构造函数,没有复制或移动可能是由R​​VO和NRVO。

That's not aggregate initialization at all, it's uniform initialization, which basically in this case means calling the constructor, and the no copy or move is probably done by RVO and NRVO.

请注意,当我将 B 更改为以下内容时:

Note that when I change B to the following:

struct B
{
  A a;
  B(const A& a_) : a(a_) {}
  B(A&& a_) : a(std::move(a_)) {}
};

执行移动。

如果这只是统一的初始化,只是调用构造函数并且什么都没有做特殊的,那么我该如何写一个允许移动的构造函数?

So if this is just uniform initialization and just calling the constructor and doing nothing special, then how do I write a constructor that allows the move to be elided?

或者是GCC只是没有在这里移动,当它是有效的,如果这样做,如果是,有一个编译器和优化设置,将移除移动? / p>

Or is GCC just not eliding the move here when it is valid to do so, and if so, is there a compiler and optimization setting that will elide the move?

推荐答案

根据新标准第8.5.1节(Aggretates),一个足够简单的类型(例如没有用户定义的构造函数)符合资格作为聚合。对于这样的聚合 Foo ,写 Foo x {a,b,...}; 列表项。

According to the new standard, clause 8.5.1 (Aggretates), a sufficiently simple type (e.g. no user-defined constructors) qualifies as an aggregate. For such an aggregate Foo, writing Foo x{a, b, ... }; will construct the members from the list items.

简单示例:

struct A
{
  std::unordered_map<int, int> a;
  std::string b;
  std::array<int,4> c;
  MyClass d; // Only constructor is MyClass(int, int)
};

// Usage:
 A x{{{1,-1}, {12, -2}}, "meow", {1,2,3,4}, MyClass(4,4)};
// Alternative:
 A x{{{1,-1}, {12, -2}}, "meow", {1,2,3,4}, {4,4}};

对象 x 相关构造函数执行到位。没有地图或字符串或MyClasses曾被复制或移动。注意,两个变量在底部做同样的事情。你甚至可以使MyClass的副本和移动构造函数私人的,如果你喜欢。

The object x is constructed with all the relevant constructors executed in place. No maps or strings or MyClasses ever get copied or moved around. Note that both variants at at the bottom do the same thing. You can even make MyClass's copy and move constructors private if you like.

这篇关于什么时候聚合初始化在C ++ 11中有效?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆