Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is C++17 copy elision applied to placement new?

Tags:

c++

c++17

I am writing a generic interface for scripting languages and need to call functions that return an object and put the resulting object in a space provided by the scripting language. I have tested with clang++ on Mac OS and the following seems to do the copy/move elision:

class T {
public:
    T() {}
    T(const T &t) {
        std::cout << "Copy" << std::endl;
    }
    T(T&&t) : x(t.x) {
        std::cout << "Move" << std::endl;
    }
private:
    int x = 3;
};

T h()
{
    return T();
}

void buildTInto(void *p)
{
    new (p) T(h());
}

int main(int argc, char *argv[])
{
    alignas(T) char space[sizeof(T)];
    buildTInto(space);
}

Running this code does not print anything. Reading the cpp reference description of copy elision seems to indicate this is the correct behavior, given the example they give which only calls one constructor:

T x = T(T(f())); // only one call to default constructor of T, to initialize x

I think my code is very much similar as without copy elision, the move constructor would be called (just like the T(T(f())) would call two move construction).

Not being a spec lawyer, I am curious if my understanding is correct and I wonder if all C++17 capable compilers do this correctly?

like image 920
Michel Avatar asked Sep 14 '25 23:09

Michel


1 Answers

Guaranteed elision (aka: C++17's definition of prvalues) applies to the initialization of any object of type T with a prvalue of the same type. That includes objects created by new expressions, including placement new forms.

Indeed, you don't even have to repeat the type at the point of invoking the new expression: new(p) auto(h()); ensures the obligate condition for guaranteed elision.

like image 57
Nicol Bolas Avatar answered Sep 16 '25 19:09

Nicol Bolas