2015-05-29 65 views
1

我是相当新的节目在C++中,我想知道的东西: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; 
} 

还是我看到这错了吗?

在此先感谢

+2

看到这一点:http://stackoverflow.com/questions/ 12953127/what-are-copy-elision-and-return-value-optimization – NathanOliver

+3

谁会释放这些对象?这里'a + b + c'? – StoryTeller

+1

总是使用delete删除对象(有一个二元运算符,您可能会遇到内存泄漏)。第一种方法很好(看看返回值优化) –

回答

2

试图讲道理是没有估计性能的特别准确的方法:实际上你需要一个程序写入措施一个实现是否比另一种更好。

有很多方法根本不会发生副本;指定的返回值优化(NRVO)和移动分配在这里是相关的想法。

即使您决定要做类似于您的建议的事情,也不应该像现在这样执行它,因为它具有错误的语义:您有operator+返回一个指向事物的指针而不是事情。另外,使用指针(尤其是裸指针)的工作是有风险的,因为它给了你更多犯错的机会。

如果你想要沿着这些线实现某些东西,你需要将指针语义包装在一个提供值语义的类中。

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.