Question

Here is some code I wrote to illustrate my question:

struct Foo
{
    Foo() {}
    Foo( Foo && );
    Foo( const Foo & ) = delete;
};

Foo GetFoo()
{
    return Foo();
}

int main()
{
    Foo f = GetFoo();
}

The deleted copy constructor prevents an implicit default move constructor, so I have to explicitely declare one. But I am neither using "= default" nor providing an implementation for it, yet the whole thing compiles and links properly. If I remove the declaration, it won't compile anymore.

I find it really surprising that the linker isn't complaining about the missing move constructor. Could you please help me understand why?

Was it helpful?

Solution

When initializing a variable in the form type identifier = Function(), the compiler affirms that a copy/move constructor is declared as usable, and then ignores it and tries to construct from the right side directly ("copy/move elision"). Then it has Function construct the variable directly into main, to skip a move/copy (this is "return value optimization"). These sort of work together and bypass any and all moves/copies, and Function ends up constructing f directly. Since the move constructor wasn't actually used, the linker didn't look for it, and thus failed to notice the missing definition.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top