• 复制构造,赋值操作符,const重要性


    原文地址:http://www.coderess.com/?p=55

    什么是复制构造?

    复制构造是类或结构体的一种特殊的拷贝已存在实例构造函数。根据C++标准,复制构造函数可以有以下几种形式:

      MyClass( const MyClass& other );  MyClass( MyClass& other );  MyClass( volatile const MyClass& other );  MyClass( volatile MyClass& other );

    注意不要写成以下形式,尽管它们也能够实现同样的事:

      MyClass( MyClass* other );  MyClass( const MyClass* other );  MyClass( MyClass other );

     

    什么时候需要写自己的复制构造函数?

    首先,你需要明白假如你没声明一个复制构造函数,编译器会给你提供默认的构造函数。这个默认的构造函数能智能地(member-wise)复制源对象,比如这个类:

    class MyClass { int x; char c; std::string s; };

    编译器提供的默认构造函数相当以下功能:

     MyClass::MyClass( const MyClass& other ) :     x( other.x ), c( other.c ), s( other.s )  {}

    在很多情况下,这是足够的。然而,有些情景下member-wise的拷贝方式是不够的。尤为常见的原因是默认的复制构造会产生野指针(raw pointer),这个时候你需要深复制指针成员,这是当你不是想复制指针本身,而是想复制指针指向的内容。为什么需要深复制?这是因为通常一个实例拥有指针,同时在某些时候它也负责删除这个指针,比如析构函数发生的前一刻。假如两个对象都析构调用 delete 函数删除非空指针成员,会导致堆栈溢出。

    使用编译器提供的默认复制构造函数,很少情况不会出现野指针,因此默认构造函数是不足够的。你也可以使用引用计数。比如boost::shared_ptr<>。

    正确使用const  (Const correctness)

    当通过引用的方式传递参数给函数或者构造对象时,要很小心地正确使用const。仅仅当函数会修改传递的函数才使用non-canst引用,否则就应该使用const引用。

    为什么强调要这样? 这是一个C++标注的小条款:non-const 引用不能绑定到临时对象,临时对象时一个没有变量名的实例,比如:

    std::string( "Hello world" );

    是一个临时对象,因为没有变量名。下面一个不是临时对象:

    std::string s( "Hello world" );

    这个实用的提醒有什么用?请看下面:

    // Improperly declared function:  parameter should be const reference:  void print_me_bad( std::string& s ) {      std::cout << s << std::endl;  }  // Properly declared function: function has no intent to modify s:  void print_me_good( const std::string& s ) {      std::cout << s << std::endl;  }  std::string hello( "Hello" );  print_me_bad( hello );  // Compiles ok; hello is not a temporary  print_me_bad( std::string( "World" ) );  // Compile error; temporary object  print_me_bad( "!" ); // Compile error; compiler wants to construct temporary                       // std::string from const char*  print_me_good( hello ); // Compiles ok  print_me_good( std::string( "World" ) ); // Compiles ok  print_me_good( "!" ); // Compiles ok 

    很多STL的容器和算法都要求一个对象时可拷贝的。通常,这意味着你需要有实用const传引用的复制构造函数。 (最近一个搞了很久的错误就是这个问题,所以觉得这篇文章很好,就翻译过来分享了)

    插曲(译者经历):

    我在使用list的时候,用到了replace泛型算法:

    template < class ForwardIterator, class T >  void replace ( ForwardIterator first, ForwardIterator last,  const T& old_value, const T& new_value )
    {  
    for (; first != last; ++first)    
    if (*first == old_value) *first=new_value;
    }

    很明显这个算法要求对象具有 == 操作符来比较。我也为对象重载了 == 操作符:

    查看完整文章:http://www.coderess.com/?p=55#more-55

    点击这里给我发消息
  • 相关阅读:
    ios NSString format 保留小数点 float double
    IOS中延时执行的几种方式的比较和汇总
    ioss使用xcode常用快捷键
    iphone 6plus 下app里的状态栏和界面会被放大的问题//以及设置APP闪屏页/APP图标流程
    iostbleView刷新后显示指定cell
    iOS-打包成ipa的4种方法
    iosttableViewCell右侧的箭头,圆形等
    Linux学习之CentOS(二十)------vi/vim 按键说明
    gzip
    bzip2
  • 原文地址:https://www.cnblogs.com/charm/p/1822273.html
Copyright © 2020-2023  润新知