A fully compliant C++14 compiler with all defects solved has at least one bit of code it is mandated to make more efficient than the C++11 version.
struct one_byte { char x = 7; };
struct cheap_move {
std::vector<one_byte> state{1000000}; // 1 mb of state, cheap to move
};
struct test_type {
test_type(test_type const&)=default;
test_type(test_type &&)=default;
// can construct from a cheap_move via either copy or move:
test_type(cheap_move const&y):x(y){}
test_type(cheap_move &&y):x(std::move(y)){}
cheap_move x;
};
test_type test_func() {
cheap_move m;
return m;
}
the return m;
in a C++11 compliant compiler will copy 1 megabyte of memory. In a C++14 compiler with defect 1579 implemented, it will copy 3 pointers (well, move 1 vector).
This is because in C++11, the implicit convert-to-rvalue only occurs if the types match exactly. Under that above defect report (listed as C++14), it occurs if there is an rvalue-consuming constructor that matches. So C++14 moves into the return value, while C++11 copies into the return value.
(@T.C. tracked down the defect report above).
Note that not all C++14 compilers implement that fix to that defect. Both clang and gcc over at http://coliru.stacked-crooked.com/ at this point do not implement the fix to that defect in C++14 or C++1z mode.
A less contrived example is:
struct modulate {
std::vector<double> state;
double operator()(double x)const{
double r = 0;
for (double v:state) {
r*=x;
r+=v;
}
return r;
}
};
std::function< double(double) > f( std::vector<double> state ) {
auto m = modulate{std::move(state)};
return m;
}
The return implicitly moves in C++14, and copies in C++11.
Note that a simple std::move(m)
would make C++11 do the same thing as C++14, but the rule that "you don't move
returned local variables" leads people to avoid that (as it blocks elision): such an "error" would be common, given the general rule.
In C++11 this "error" leads to inefficiency above, but it is no longer an error in C++14.