zoukankan      html  css  js  c++  java
  • Effective C++ Item 25 考虑写出一个不抛异常的swap函数

    本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie


    经验:当std::swap对你的类型效率不高时,提供一个swap成员函数,并确定这个函数不抛出异常

    演示样例:
    stl里的swap算法
    namespace std{
    	template<typename T>
    	void swap(T &a, T &b){
    		T temp(a);
    		a = b;
    		b = temp;
    	}
    }
    
    
    //“pimpl手法”(pointer to implementation) --> 文件间的编译依存度
    class WidgetImpl{
    public:
    	//...
    private:
    	int a, b, c;
    	std::vector<double> v;
    	//...
    }
    
    
    class Widget{
    public:
    	Widget(const Widget &rhs);
    	Widget &operator=(const Widget &rhs){ //返回的为什么是引用?--> 就应该是引用,參见Item10令operator=返回一个reference to *this。
    										  //这里和Item28不一样,那里说的是不要返回handler指向对象 内部 成分。

    //... *pImpl = *(rhs.pImpl); //... } //... private: WidgetImpl *pImpl; }


    解析:一旦要转换两个Widget对象值,我们唯一须要做的就是转换其pImpl指针。但缺省的swap算法不知道这一点。它不仅仅复制三个Widgets,还复制三个WidgetImpl对象。

    纠正:将std::swap针对Widget特化
    通常我们不被同意改变std命名空间的不论什么东西。但能够为标准template制造特化版本号
    namespace std{ //这是std::swap针对“T是Widget”的特化版本号。

    眼下还不能通过编译 template<> void swap<Widget>(Widget &a, Widget &b){ swap(a.pImpl, b.pImpl); } }


    经验:假设你提供一个member swap。也该提供一个non-member swap用来调用前者。对于 classes(而非templates)。也请特化std::swap

    演示样例:
    namespace WidgetStuff{
    	class Widget{  //能正常编译,且与STL容器有一致性。

    由于全部STL容器也都提供有public swap成员函数和std::swap特化版本号 public: //... void swap(Widget &other){ //调用swap时应针对std::swap使用using声明式。然后调用swap而且不带不论什么“命名空间资格修饰” using std::swap; swap(pImpl, other.pImpl); } //... }; void swap(Widget &a, Widget &b){ //non-member swap 函数。这里并不属于std命名空间 a.swap(b); } } namespace std{ template<> void swap<Widget>(Widget &a, Widget &b){ a.swap(b); } }


    经验:为“用户定义类型”进行std templates全特化是好的。但千万不要尝试在std内增加某些对std而言全新的东西
    演示样例:
    template<typename T>
    class WidgetImpl{
    	//...
    }
    template<typename T>
    class Widget{
    	//...
    }
    
    
    namespace std{ //错误,不合法 --> function template仅仅能全特化。不能偏特化
    	template<typename T>
    	void swap<Widget<T> >(Widget<T> &a, Widget<T> &b){
    		a.swap(b);
    	}
    }
    
    
    namespace std{
    	template<typename T> //std::swap的一个重载版本号,不合法 --> std不同意加入新的的templates
    	void swap(Widget<T> &a, Widget<T> &b){
    		a.swap(b);
    	}
    }
    

  • 相关阅读:
    MySql 用户 及权限操作
    MAC 重置MySQL root 密码
    在mac系统安装Apache Tomcat的详细步骤[转]
    Maven:mirror和repository 区别
    ES6 入门系列
    转场动画CALayer (Transition)
    OC 异常处理
    Foundation 框架
    Enum枚举
    Invalid App Store Icon. The App Store Icon in the asset catalog in 'xxx.app' can’t be transparent nor contain an alpha channel.
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/7264353.html
Copyright © 2011-2022 走看看