• 复习几个C++概念:声明与定义、传值与拷贝构造、初始化和赋值


      今天看了看Effective C++中文版第2版导读部分,里面说了不少东西,其中就包括标题里的这些概念。感觉自己对这些概念还不是很熟悉,于是摘抄一些内容放到博客里,以方便自己做笔记,回头记忆。

    1、声明与定义

      所谓声明(declaration),是用来将一个object、function、class或template的型别名称告诉编译器声明式并不带有细节信息。下面统统都是声明:

        extern int x; // object declaration

        int numDigits( int number ); // function declaration

        class Clock; // class declaration

        template<typename T>

        class SmartPointer; // template declaration

      所谓定义(definition),是用来将细节信息提供给编译器。对object而言,其定义式是编译器为它配置内存的地点。对function 或function template而言,其定义式提供函数本体(function body)。对class 或class template而言,其定义式必须列出该class 或template的所有members:

        int x; // object definition

        int numDigits( int number) {...} // function definition

        class Clock { // class definition

        public:

          Clock(); ~Clock(); int hour() const; int minute() const; int second() const; ...     

        };

        template<typename T> 

        class SmartPointer {

        public : ...  

        }; // template definition

    2、传值与拷贝构造

      (这两个概念自己之前反正是联系不到一块,现在写的时候也不是很清楚,没有整体概念,哪位朋友有比较深刻的体验,麻烦告知小弟一下~~)

      引用Effective C++ P7的代码来进行下面的概念文字说明:  

     1 const String operator+ ( String s1, String s2 ) // s1、s2 by value
    2 {
    3 String temp;
    4 delete []temp.data;
    5 temp.data = new char[ strlen(s1.data) + strlen(s2.data) + 1];
    6 strcpy( temp.data, s1.data );
    7 strcat( temp.data, s2.data );
    8 return temp; // 传回值 by value
    9 }
    10
    11 String a("Hello");
    12 String b("World");
    13 String c = a + b;

      这个函数效率是很低的,当然大家都知道,下面一段话也就是大家心里想的原因:

      这里不论参数还是运算结果都是以by value 方式传递,所以在operator+进行过程中,会有一个copy constructor被调用,用以将a当做s1的初值,再有一个copy constructor被调用,用以将b当做s2的初值,再有一个copy constructor被唤起,用以将temp当做c的初值。事实上,只要编译器决定产生中阶的暂时性对象,就会需要一些copy constructor调用动作。重点是:pass-by-value便是“调用copy constructor”的同义词

    3、初始化和赋值

      对象的initialization行为发生在它初次获得一个值的时候。对于“带有constructors”的classes活structs,initialization总是经由调用某个constructor达成。这和对象的assignment动作不同,后者发生于“已初始化之对象被assignment新值”的时候:

      string s1; // initializaition

      string s2("Hello"); // initialization

      string s3 = s2; // initialization

      s1 = s3; // assignment

      纯粹从操作观点来看,initialization和assignment之间的差异在于前者由constructor执行,后者由operator=执行。换句话说,这两个动作对应不同的函数动作。

      C++严格区分此二者,原因是上述两个函数所考虑的事情不同。Constructors通常必须检验其引数的有效性,而大部分assignment运算符不必如此,因为其引数必然是合法的(因为已被建构完成)。另一方面,assignment动作的目标对象并非是尚未构造完成的对象,而是可能已经拥有配置得来的资源。在新资源可被赋值过去之前,旧资源通常必须先行释放。这里所谓的资源通常是指内存。在assignment运算符为一个新值配置内存之前,必须先释放旧值的内存。 

      下面以实际代码来说明上述文字。在代码之前,先行给出代码的解释:

      constructor必须检验其参数的有效性,并确保member data都被适当地初始化;而assignment运算符认定其参数是合法的,反倒是它会①侦测诸如“自己复制给自己”这样的病态情况,或是②集中心力确保“配置新内存之前先释放旧有内存”。这两个函数的差异,象征对象initialization和对象assignment两者的差异。

     1 String::String( const char *value )
    2 {
    3 if ( value )
    4 { //确保member data都被适当初始化
    5 data = new char[strlen(value) + 1];
    6 strcpy(data,value);
    7 }
    8 else
    9 { //确保member data都被适当初始化
    10 data = new char[1];
    11 *data = '\0';
    12 }
    13 }
    14
    15 String& String::operator=(const String& rhs)
    16 {
    17 if ( this == &rhs ) //①
    18 {
    19 return *this;
    20 }
    21
    22 delete []data; //②
    23 data = new char[strlen(rhs.data) + 1];
    24 strcpy(data, rhs.data);
    25
    26 return *this;
    27 }

    结束~~

  • 相关阅读:
    野路子码农系列(7)近期花里胡哨技巧汇总
    野路子码农系列(6)有关线下验证集选取的思考
    野路子码农(5)Python中的装饰器,可能是最通俗的解说
    野路子码农(4)挖掘机云端部署小试
    野路子码农系列(3)plotly可视化的简单套路
    野路子码农系列(2)Python中的类,可能是最通俗的解说
    野路子码农系列(1) 创建Web API
    pandas技巧两则——列内元素统计和列内元素排序
    Windows环境下Anaconda安装TensorFlow的避坑指南
    让米帝领事馆给你报空气质量(动态网页爬取及简单的数据整理)
  • 原文地址:https://www.cnblogs.com/ziyoudefeng/p/2423634.html
Copyright © 2020-2023  润新知