Is the default move constructor an optimized compiler?

I have a std :: multimap of the following type:

 typedef std::multimap<std::pair<bool,uint32_t>, FooObject>

      

FooObject has a default move copy and declares the declared constructors:

   FooObject(FooObject&& v) = default;
   FooObject& operator=(FooObject&& other)=default;

      

The copy / assign constructors are private to disable implicit copy.

So, I should be able to insert a pair into a card like this:

mymap.emplace(std::make_pair(false,32),FooObject());

      

This displays a list of errors with a number at the end:

error C2660: 'std :: pair :: pair': function does not take 2 arguments

If I declare copy destination constructors without default, then it compiles fine.

   FooObject(FooObject&& v){}
   FooObject& operator=(FooObject&& other){}

      

Why? Does the compiler optimize these constructors when marked with the "default" keyword? I am using MSVC140

UPDATE:

Based on the comments below, I found the reason - FooObject has a non-copyable instance. Here is the FooObject:

#define NO_COPY_ASSIGN(TypeName)   \                                                     
  TypeName (const TypeName &);     \                                                                
  void operator= (const TypeName &);

class FooObject
{
private:
   NO_COPY_ASSIGN(FooObject)
public:
    struct FooStruct
    {
        FooBuffer   frameBuffer;   //<--Here it is
    }fooStruct;

    FooObject(){}


    /** Move constructor to allow insert into vector without copy */
    FooObject(FooObject&& v) = default;
    FooObject& operator=(FooObject&& other) = default;

};

      

* FooBuffer also has its own copy / assignment private. But I still don't understand why to replace "default" with {} fixes. Explain, please.

+3


source to share


2 answers


Difference between

FooObject(FooObject&& v) = default;

      

and

FooObject(FooObject&& v){}

      

This is that the former will emit a constructor that moves each element from v

, and the latter by default builds each element and does nothing with v

.

Since it FooBuffer

does not move, it means that the compiler will delete FooObject(FooObject&& v) = default;

as it will be ill-formed.

With FooObject(FooObject&& v){}

you, you don't have this problem, since you never try to move items v

. Since there is no member initialization list, the compiler will add one for you, which only creates members by default.



You can see this behavior more clearly with this:

struct Moveable
{
    Moveable() = default;
    Moveable(Moveable&&) { std::cout << "in Moveable(Moveable&&)\n"; }
};

struct Foo
{
    Foo() = default;
    Foo(Foo&&) = default;
    Moveable m;
};

struct Bar
{
    Bar() = default;
    Bar(Bar&&){}
    Moveable m;
};

int main()
{
    Foo f;
    Bar b;
    std::cout << "test_f\n";
    Foo test_f(std::move(f));
    std::cout << "test_b\n";
    Bar test_b(std::move(b));
}

      

which outputs

test_f
in Moveable(Moveable&&)
test_b

      

Indicates that Bar

nothing is being moved in the move constructor .

+1


source


Your problem is that one of the members is FooObject

unable to move, which prevents the compiler from generating default move operations.



The versions of the move operations you {}

perform do not (in particular: they do not actually perform the move operation) on members FooObject

and are therefore legal.

+2


source







All Articles