如果你愿意使用 C++11,你可以使用“移动语义”。让我先举一个例子来解释:
class expensive {
public:
expensive() : n(0), V(NULL) {}
expensive(int _n) {
n = _n;
V = new int[_n];
for (int i = 0; i < n; ++i) V[i] = i*i;
}
expensive(const expensive& rhs) { // copy constructor
n = rhs.n;
V = new int[n];
for (int i = 0; i < n; ++i) V[i] = rhs.V[i];
}
expensive(expensive&& rhs) { //move constructor
n = rhs.n;
V = rhs.V;
rhs.n = -1;
rhs.V = NULL;
printf("Moving\n");
}
~expensive() {
if (n == -1) printf("Destroying 'moved' instance\n");
if (V) delete [] V;
}
private:
int *V;
int n;
};
expensive f(int x) {
expensive temp(50);
expensive temp2(temp); // Copy temp to temp2, both are valid now
expensive temp3(std::move(temp)); // Move temp to temp3, temp is not valid anymore
return std::move(temp2); // move temp2 to the return
}
int main() {
expensive E = f(30);
return 0;
}
这个程序的输出是:
Moving
Moving
Destroying 'moved' instance
Destroying 'moved' instance
所有普通的 STL 容器都支持移动语义。此外, std::swap 使用它(因此也使用 std::sort )。
编辑:如前所述,如果正在使用 NRVO,则最后一个 std::move 是不必要的。让我举一个更复杂的例子。这是一个玩具示例,但它应该表明我的观点。
class expensive {
... // Same definition as before
}
expensive g(int x) {
vector<expensive> V;
V.reserve(2*x);
for (int i = 1; i <= x; ++i)
V.push_back(expensive(i)); // Here the objects are moved to the vector
for (int i = 1; i <= x; ++i)
V.emplace_back(i); // Here the objects are constructed directly in the vector
return std::move(V[x/2]); // V[x/2] is moved to the answer
}
int main() {
expensive x(g(2)); // 3 objects should be moved, 2 in push_back and one on the return
return 0;
}