简体   繁体   中英

C++11: 'decltype class instance declaration' with std::move( ) doesn't call 'move constructor.' Why?

I recently started using c++ and I chose to learn c++11 features. But how c++ codes run is sometimes not so tangible.

below is my code. At the part with decltype(std::move(sample)) sample2 = std::move(sample); I'm not sure why this line doesn't call move constructor. Could you explain why?

#include <iostream>

class AAA
{
   public:
      AAA() { std::cout << "default constructor" << std::endl; }
      AAA(const AAA& cs) { std::cout << "copy constructor" << std::endl; }
      AAA(AAA&& cs) { std::cout << "move constructor" << std::endl; }
      ~AAA() { std::cout << "destructor" << std::endl; }
};

int main(int argc, char* args[])
{
    AAA sample;
// ((right here))
    decltype(std::move(sample)) sample2 = std::move(sample); 
    return 0;
}

It is compiled on [ ubuntu 16.04 LTS ] with [ gcc 5.4.0 ]

original code : https://ide.geeksforgeeks.org/tALvLuSNbN

Your snippet expands to

AAA&& sample2 = std::move(sample);

which binds an rvalue (the result of std::move(sample) ) to an rvalue reference ( sample2 ). No new object is constructed, and hence no such constructor is called.

The function std::move<T> returns a T && , so for std::move(sample) it returns AAA && . This is an rvalue reference and behave a lot like an lvalue reference (a type like AAA & would be an lvalue reference) in that they both are alias to objects that already exist.

It's important to understand that std::move does not in itself cause anything to be moved. It simply returns an rvalue reference to the argument it's given. For example std::move(foo); alone does absolutely nothing. It's only when the result is used to initialize or assign to an object that it becomes useful.

For example auto bar = std::move(foo); will return an rvalue reference to foo and use that reference to call bar 's constructor.

To answer the question, since std::move(sample) returns a AAA && , the line in question is the same as AAA && sample2 = std::move(sample); . The behavior is practically the same as AAA & sample2 = sample; . In both cases, you are initializing a reference to an existing object and no new object needs to be constructed.

If your goal is to move sample into a new AAA , the correct line would be auto sample2 = std::move(sample); like you do with sample3 . Though beware that the line sample3 is moving from an already moved-from sample .

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