I have the following code to test the move constructor in C++. The class MovableArray
is designed using the copy and swap idiom. I want to test that move semantics actually works.
However, it seems that the expression in main
function with printSize(MovableArray(30))
doesn't invoke the move constructor.
I managed to get the line with 40
invoke move constructor by telling the compiler not to perform copy elision. So I am guessing the reason behind the call with 30
is also due to compiler optimization. However, I didn't find a flag from clang documentation.
Could anyone point out the reason? Thanks.
#include <algorithm>
#include <iostream>
#include <utility>
class MovableArray
{
public:
MovableArray()
: size_{ 0 }
, data_{ nullptr }
{}
explicit MovableArray(int size) // ctor
: size_(size)
, data_{ new int[size]() } {};
~MovableArray() // dtor
{
delete[] data_;
std::cout << "deleted array of size " << size_ << std::endl;
};
MovableArray(const MovableArray& other) // copy constructor
: size_{ other.size_ }
, data_{ new int[size_]() }
{
std::copy(other.data_, other.data_ + other.size_, this->data_);
std::cout << "Array of size " << size_ << " is copied\n";
}
MovableArray(MovableArray&& other) // move constructor
: MovableArray()
{
swap(*this, other);
std::cout << "Array of size " << size_ << " is moved\n";
}
friend void swap(MovableArray& a, MovableArray& b) throw()
{
using std::swap;
swap(a.data_, b.data_);
swap(a.size_, b.size_);
}
int size() const { return this->size_; }
int operator[](int i) const { return data_[i]; }
int& operator[](int i) { return data_[i]; }
private:
MovableArray& operator=(const MovableArray& rhs); // copy operator
MovableArray& operator=(MovableArray&& rhs); // move operator
// MovableArray& operator=(MovableArray rhs); // both
int size_;
int* data_;
};
void
printSize(MovableArray a)
{
/* for (int i = 0; i < a.size(); ++i) */
/* std::cout << a[i] << "\t"; */
/* std::cout << std::endl; */
std::cout << "Size of array is " << a.size() << std::endl;
}
MovableArray
createArray(int size)
{
auto ret = MovableArray(size);
return ret;
}
int
main()
{
MovableArray a{ 20 };
// copied
printSize(a);
// explicitly moved
printSize(std::move(a));
// implicitly moved, why not working? TODO
printSize(MovableArray(30));
// implicitly moved
// need to be compile with option
// -fno-elide-constructors
printSize(createArray(40));
}
The output I got is
Array of size 20 is copied
Size of array is 20
deleted array of size 20
Array of size 20 is moved
Size of array is 20
deleted array of size 20
Size of array is 30
deleted array of size 30
Array of size 40 is moved
deleted array of size 0
Size of array is 40
deleted array of size 40
deleted array of size 0
Aucun commentaire:
Enregistrer un commentaire