Cli*_*ton 10 c++ optimization aggregate aggregate-initialization 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()};
}
Run Code Online (Sandbox Code Playgroud)
在这里,我认为struct A不是一个聚合,因为它既有非平凡的构造函数,也有std::string我认为不是聚合的成员.这可能意味着它B也不是一个聚合体.
然而,我可以聚合初始化B.此外,这可以在没有调用复制或移动构造函数的情况下完成(例如,在ideone上的C++ 0x GCC 4.5.1 ).
这种行为似乎是一种有用的优化,特别是对于没有廉价移动的大型堆栈类型的组合.
我的问题是:这种聚合初始化何时在C++ 0x下有效?
编辑+跟进问题:
下面的DeadMG回答如下:
这根本不是聚合初始化,它是统一初始化,基本上在这种情况下意味着调用构造函数,并且没有复制或移动可能由RVO和NRVO完成.
请注意,当我更改B为以下内容时:
struct B
{
A a;
B(const A& a_) : a(a_) {}
B(A&& a_) : a(std::move(a_)) {}
};
Run Code Online (Sandbox Code Playgroud)
移动被执行.
因此,如果这只是统一初始化并且只是调用构造函数并且没有做任何特殊操作,那么如何编写允许移动被省略的构造函数呢?
或者GCC只是在这样做有效的时候没有忽略此举,如果是这样的话,是否有一个编译器和优化设置会忽略此举?
根据新标准第8.5.1节(Aggretates),一个足够简单的类型(例如,没有用户定义的构造函数)有资格作为聚合.对于这样的聚合Foo,写入Foo x{a, b, ... };将从列表项构造成员.
简单的例子:
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}};
Run Code Online (Sandbox Code Playgroud)
x构造对象时,所有相关的构造函数都在适当的位置执行.没有地图或字符串或MyClass被复制或移动.请注意,底部的两个变体都做同样的事情.如果愿意,您甚至可以创建MyClass的副本并将构造函数移动为私有.
| 归档时间: |
|
| 查看次数: |
1840 次 |
| 最近记录: |