我是用C ++编程的新手,我想知道一些事情:
每当我在C ++中看到运算符重载时,就会这样做:
#ifndef STONE_H
#define STONE_H
class Stone {
private:
int weight;
public:
.......
Stone operator+(const Stone& s) {
Stone stone;
stone.weight = this->weight + s.weight;
return stone;
}
.......
}
#endif
但是当调用“+”运算符时,它会创建一个对象“stone”,并返回一个副本。处理大型物体时,这对性能不利?
如下例所示,使用动态内存不是更好:
Stone * operator+(const Stone& s) {
Stone * stone = new Stone;
stone->weight = this->weight + s.weight;
return stone;
}
或者我看到了这个错误?
提前致谢
答案 0 :(得分:2)
尝试推理出来并不是特别准确的估算性能的方法:您需要实际编写一个程序来度量一个实现是否优于另一个实现。
有很多方法可以完全不复制;命名的返回值优化(NRVO)和移动分配是相关的想法。
即使你决定要做一些像你的建议一样的事情,你也不应该像你一样实现它,因为它有错误的语义:你已经operator+
返回指针到事物而不是一件事。此外,使用指针(特别是裸指针)是有风险的,因为它为您提供了更多犯错的机会。
如果你想在这些行上实现某些东西,你需要将指针语义包装在一个提供值语义的类中。
答案 1 :(得分:0)
根据现行标准,这有点不同:
#include <iostream>
class big {
int* v; // Demonstration purposes. A smart pointer or a standard container would be better.
public:
big& operator+=(big& o) {
for (int i=0;i<1000;++i) {
v[i] += o.v[i];
}
return *this;
}
big(int val = 0)
: v{new int[1000]} // We're using RAII to prevent resource leaking.
{
std::cout << "a construction.\n";
for (int i=0;i<1000;++i) {
v[i] = val;
}
}
// Copy constructor
big(big& o)
: v{new int[1000]}
{
std::cout << "a copy construction.\n";
for (int i=0;i<1000;++i) {
v[i] = o.v[i];
}
}
// Move assignment
big& operator=(big&& o) {
std::cout << "a move assignment.\n";
if (v) delete[] v;
v = o.v;
o.v = nullptr;
}
// Move constructor
big (big&& o) {
std::cout << "a move construction.\n";
v = o.v;
o.v = nullptr;
}
~big() {
if (v) delete[] v;
}
};
// a will be move-constructed if using a temporary, or copy-contructed if not.
// The result will always be passed by a cheap move
big operator+(big a, big& b) {
return std::move(a += b);
}
int main() {
big a{1};
big b{2};
big c{3};
big d = a+b+c;
}
输出:(添加了评论)
a construction. // Constructed a
a construction. // Constructed b
a construction. // Constructed c
a copy construction. // a+b <- a copied into parameter "a" of operator+. b is passed by reference.
a move construction. // The temporary from the operation above, moved into parameter "a" of operator+. c is passed by reference.
a move construction. // d is move constructed from the temporary generated by a+b+c.