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)……

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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值