简体   繁体   中英

Can copy elision be perfomed in aggregate initialization in c++17?

Given:

//C++17
#include <string>
struct Foo {
    int i;
    std::string str;
};

int main() {
    Foo foo{1, std::string("Hello, world!")};
}

Can Foo::i and Foo::str be directly initialized from 1 and std::string(...) instead of being copied into them, and explain why can/can't using C++17 standard(probably some code for testing purpose)?

If they can't, how many copies are required?

Aggregate initialization basically performs element-wise copy-initialization. So this:

struct Foo {
    int i;
    std::string str;
};

Foo foo{1, std::string("Hello, world!")};

does the same initializations as:

int i = 1;
std::string str = std::string("Hello, world!");

And we have a new rule in C++17 that says that:

If the initializer expression is a prvalue and the cv-unqualified version of the source type is the same class as the class of the destination, the initializer expression is used to initialize the destination object. [ Example: T x = T(T(T())); calls the T default constructor to initialize x . — end example ]

which means that the second initialization must behave as if you'd written:

std::string str("Hello, world!");

That is, zero copies.


A nice demonstration of the new rule is the following example:

struct X {
    X(int ) { }
    X(X&& ) = delete;
};

struct Y {
    X x;
};

int main() {
    Y y{X{4}}; // ill-formed in C++14 due to deleted move ctor
               // ok in C++17, no move required
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM