I'm trying to understand the new move constructor from C++11 following an example from the book "Professional C++", 2nd ed., chapter 9, page 279.
Here is my class header file Spreadsheet.h:
class Spreadsheet
{
public:
Spreadsheet(int inWidth = kMaxWidth, int inHeight = kMaxHeight);
Spreadsheet(const Spreadsheet& src);
Spreadsheet(Spreadsheet&& src);
~Spreadsheet();
int getId() const;
int getWidth() const;
int getHeight() const;
void setCellAt(int x, int y, const SpreadsheetCell& cell);
SpreadsheetCell getCellAt(int x, int y) const;
Spreadsheet& operator=(const Spreadsheet& rhs);
Spreadsheet& operator=(Spreadsheet&& rhs);
private:
bool inRange(int val, int upper) const;
void copyFrom(const Spreadsheet& src);
void moveFrom(Spreadsheet& src);
void freeMemory();
int mWidth, mHeight, mId;
SpreadsheetCell** mCells;
static int sCounter;
const static int kMaxWidth = 100;
const static int kMaxHeight = 100;
};
And here are some snippets from Spreadsheet.cpp:
Spreadsheet::Spreadsheet(Spreadsheet&& src)
{
std::cout << "Move ctor" << std::endl;
moveFrom(src);
}
void Spreadsheet::moveFrom(Spreadsheet& src)
{
mId = src.mId;
mWidth = src.mWidth;
mHeight = src.mHeight;
mCells = src.mCells;
src.mWidth = 0;
src.mHeight = 0;
src.mCells = nullptr;
}
Spreadsheet& Spreadsheet::operator=(Spreadsheet&& rhs)
{
std::cout << "Move assignment" << std::endl;
if (this == &rhs) {
return *this;
}
freeMemory();
moveFrom(rhs);
return *this;
}
void Spreadsheet::freeMemory() {
for (int i = 0; i < mWidth; i++) {
delete [] mCells[i];
}
delete [] mCells;
mCells = nullptr;
}
Then, I got this on my main:
std::vector<Spreadsheet> vec;
for (int i = 0; i < 3; i++) {
std::cout << "Iteration " << i << std::endl;
vec.push_back(Spreadsheet(1, 1));
std::cout << vec[i].getId() << std::endl;
std::cout << std::endl;
}
The programs output is like:
Iteration 0 Normal ctor Move ctor 0 Iteration 1 Normal ctor Move ctor Copy ctor 1 Iteration 2 Normal ctor Move ctor Copy ctor Copy ctor 3
I'd expect just calls to the move ctor instead of the copy ctor for all elements, not just the first one, as the vector resizes itself to fit the new element.
I'm compiling with clang 3.3-1 and libc++ 3.3-3:
$ clang++ -Wall -g -std=c++11 -stdlib=libc++ -lc++abi \
SpreadsheetTest.cpp Spreadsheet.o SpreadsheetCell.o -o SpreadsheetTest
What I can't figure out is if there is something wrong with my implementation or it's related to std::vector
implementation which does not make use of move constructors.