zoukankan      html  css  js  c++  java
  • 复制构造,赋值操作符,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

    点击这里给我发消息
  • 相关阅读:
    Codeforces Beta Round #92 (Div. 2 Only) B. Permutations 模拟
    POJ 3281 Dining 最大流 Dinic算法
    POJ 2441 Arrange the BUlls 状压DP
    URAL 1152 Faise Mirrors 状压DP 简单题
    URAL 1039 Anniversary Party 树形DP 水题
    URAL 1018 Binary Apple Tree 树形DP 好题 经典
    pytorch中的forward前向传播机制
    .data()与.detach()的区别
    Argparse模块
    pytorch代码调试工具
  • 原文地址:https://www.cnblogs.com/charm/p/1822273.html
Copyright © 2011-2022 走看看