C++ 中让对象的拷贝成为 显式 的

C++中对象的拷贝一般使用拷贝构造函数,从而对象的拷贝大多是隐式的,使用拷贝构造函数的隐式拷贝很方便,但是编译器无法识别不必要的拷贝,虽然我们人类可以识别这些不必要的拷贝,比如在写函数原型时,忘了加&,就会引发一个这样的非必要拷贝。

如果这种情况很严重,我们可以禁用拷贝构造函数和赋值函数(声明成private),然后再提供一个显式拷贝函数,如:

class HeavyObject {
    HeavyObject(const HeavyObject&);
    HeavyObject& operator=(const HeavyObject&);
public:
    void clone_to(HeavyObject& dest) const;
    // more...
};

这种方法的确可以work,但看上去很不自然,比如:

HeavyObject x, y;
    // ...
    y.clone_to(x); // copy y to x
// 其实我们更习惯这样的表达:
    x = y.clone();

x = y.clone(); 在形式上很自然,但是实现却不容易(在C++11中实现要容易点,让 x 接受 && 即可)。

但的确可以实现:在 C++98 标准中,如果一个函数返回一个非 Primitive 的值对象,那么这个对象不能被 bind 到非 const 引用上, 但是可以被修改

我们可以利用标准的这个特点:

template<class T> struct Ref2 : T {};
template<class T> struct Ref1 {
// 作为返回值对象,Ref1 可以被修改,但不能绑定到 Ref1& 上  
    T val;  
    Ref1(const T& y) : val(y) {}  
    operator Ref2<T>&() // this is a non-const member function  
    { return static_cast<Ref2<T>&>(val); }  
};
class HeavyObject {  
    friend struct Ref1<HeavyObject>; // for Ref1 accessing the private copy-cons  
    HeavyObject(const HeavyObject&);
    HeavyObject& operator=(const HeavyObject&);  
public:
    HeavyObject() {}
    void swap(HeavyObject& y) { /*non-throw*/ }  
    void operator=(Ref2<HeavyObject>& y) {  
       // prohibit chained assign  
       this->swap(y); // y is the object created by clone  
    }  
    Ref1<HeavyObject> clone() const {  
        // copy-cons is private and has implementation  
        // assume return value optimization is enabled  
        return Ref1<HeavyObject>(*this);  
    }  
    // more...  
};  

当执行 x = y.clone() 时,clone 调用Ref1(const HeavyObject& y) 创建一个临时对象并按值返回,该对象不能 bind 到 non-const reference,但可以被修改!

接下来该对象被传给 HeavyObject::operator=,但该 operator= 只接受 Ref2& 或 const HeavyObject&,于是,编译器需要调用一个 user defined type conversion, 在这里,就是Ref1::operator Ref2&,该函数是 non-const,可以被调用(记得前面说的:不能 bind 到 non-const reference,但可以被修改,从而就可以调用
non-const member function)……

于是,接下来的事情就很简单了……

原文链接: https://www.cnblogs.com/rockeet/archive/2012/03/11/3666870.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    C++ 中让对象的拷贝成为 显式 的

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/43911

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月8日 下午8:34
下一篇 2023年2月8日 下午8:34

相关推荐