Move object without a move constructor

怎甘沉沦 提交于 2020-01-03 19:16:10

问题


One more time about this, but the related questions do not answer my question.

The standard is pretty clear:

12.8 Copying and moving class objects,
§9
If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if
— X does not have a user-declared copy constructor,
— X does not have a user-declared copy assignment operator,
— X does not have a user-declared move assignment operator,
— X does not have a user-declared destructor, and
— the move constructor would not be implicitly defined as deleted.
[ Note: When the move constructor is not implicitly declared or explicitly supplied, expressions that otherwise would have invoked the move constructor may instead invoke a copy constructor. — end note ]

So, before noticing the "Note" at the end, I expected this piece of code to fail compilation (although I knew, that moving should fallback to copying):

#include <iostream>
using std::cout;
class c
{
public:
    c() { cout << "c::c()\n"; }
    c( std::initializer_list< int > ) { cout << "c::c( std::initializer_list )\n"; };

    c( const c& ) { cout << "c::c( const c& )\n"; }
    c& operator=( const c& ) { cout << "c& c::operator=( const c& )\n"; return *this; }

    ~c() { cout << "c::~c()\n"; }

    void f() {}
};

void f( c&& cr ) { cout << "f()\n"; cr.f(); }

int main()
{
    c x;
    f( std::move( x ) );

    return 0;
}

Then I saw the note at the end, but I was still surprised, that the code above outputs:

c::c()
f()
c::~c()

Note the "missing" c::c( const c& ). Then I added

c( c&& ) = delete;
c& operator=( c&& ) = delete;

and the result is still the same.

What do I miss here?


$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609

Compiler flags: -s -O0 -march=native -pthread -std=c++11 -Wall -Wextra -DNDEBUG.


回答1:


The cr parameter from your example is a r-value reference. The reference word is significant here. It acts somewhat similar to a plane old reference that we know from c++, before c++11 was in a game, in a terms that it does not invoke any constructor... it is just "pointing" to the object you pass...

To invoke the moving constructor (or do other swap) and consume the reference we need to forward the reference further e.g. as follows:

void f( c&& cr ) {
   c cr2(std::move(cr));
}



回答2:


You didn't move any object.

std::move is actually quite confusing, because it does not move anything. only a move-constructor or a move assignment operator can move objects, what std::move do is just cast an l-value reference (&) to r-value-reference(&&).

the move constructor, or the move assignment operator can bind to the r-value-refernce(&&) and steal the object contents.



来源:https://stackoverflow.com/questions/41099950/move-object-without-a-move-constructor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!