• 总结:细节问题(C++篇)


    1. 关于拷贝构造函数;

        1,对于一个类X,如果构造函数的第一个参数是下面四种情况之一:

          a) X&
          b) const X&
          c) volatile X&
          d) const volatile X&
        且没有其他参数或其他参数都有默认值,那么这个函数是拷贝构造函数. 

        2,可以允许有下面两个拷贝构造函数同时存在:

      1. class X {      
      2. public:      
      3. X(const X&);      
      4. X(X&);            // OK   
      5. };  


        3,拷贝构造函数不能由成员函数模板生成;

      2,关于strlen()函数:

        

     1 char* c="test";
     2 
     3     int m=strlen(c);
     4 
     5     cout<<m<<endl;
     6 
     7     char* p=new char[strlen(c)+1];
     8     strcpy(p, c);
     9 
    10     cout<<p<<endl;
    11
    12    delete []p;

        第二行,m = 4;  //即统计大小是忽略最后一个空字符'';

        第七行,在申请字符数组空间时,应在strlen()所得值得基础上加1(否则最后第12行的语句会不断出错);(参看P320,p340) ; (关于strncpy()函数参看P459页笔记) ;

        第十行,输出为:"test";(引号内);

      2,关于构造顺序

        1,类成员以其在类中声明的顺序进行构造;

          class Base1

          {

            ...

          };

          class Base2

          {

            ...

          };

          class SubBase

          {

          public:

            SubBase():base2(), base1()

            {

            };

          protected:

            Base1 base1;

            Base2 base2;

          };

          在进行SubBase构造时,进入SubBase的构造函数,执行顺序为首先执行到构造函数的花括号前,接着执行

          数据成员的构造(上面为protected后面的部分),最后才执行SubBase构造函数的花括号里面的语句;

        2,派生类(即子类)的构造;

          派生类的构造总是由基类构造(即初始化)开始;

        3,多继承的构造顺序;

          1,首先,虚基类的构造函数以它们被继承的顺序进行构造;

          2,其次,非虚基类的构造按照它们被继承的顺序进行构造;

          3,再次,成员对象的构造按照它们被声明的顺序进行;

          4,最后,多继承类自己的构造(即,多继承类自己构造函数花括号里的语句)。

      3,Windows系统下,按一次回车键等于先后连续按下连个字符:

         :  回车符——回到一行的开头;

         : 换行符——跳到下一行; 

      4,指针间接引用与自增操作

        a:  sum+= * iptr;

          iptr++;

        b:  sum+= * (iptr ++);

        c:  sum+= * iptr++;

        上面的三条语句等价。原因如下:

        i:  后自增运算的优先级排在第一位(高于 间接引用运算符的优先级,第二位);

        ii: 后自增运算符返回一个经自身拷贝后得到临时对象;

      5,探究C++中while(cin>>str)该判断条件

        以下为转载,作者的分析很透彻:

        

        就在我迷茫之时看到了这么一行代码:

    /**
     *  @brief  The quick-and-easy status check.
     *
     *  This allows you to write constructs such as
     *  "if (!a_stream) ..." and "while (a_stream) ..."
     */
    operator void*() const
    return this->fail() ? 0 : const_cast<basic_ios*>(this); }

        也就是说如果 this->fail() 返回 true,这个函数则返回 0。原来问题点的核心在这里,当时提供这个方案就是为了 while(cin>>str )这种判断。

        现在的问题在于,什么情况下会调用这个函数?在执行 while (cin >> str) 时进行了(void*)这个转换吗,要验证很简单,看下面这个例子:

    #include <iostream>
     
    class my_istream
    {
    public:
        operator void * () const
        {
            return 0;
        }
    };
     
    int main ()
    {
        my_istream mi;
        my_istream &mi_ref = mi;
     
        do
        {
            std::cout << "I am right!" << std::endl;
        while (mi_ref);
     
        return 0;
    }

        假如将 operator void * () const 去掉编译器会提示如下错误:

        E:TEMP_FILE est_volatilemain.cpp||In function ‘int main()’:|
        E:TEMP_FILE est_volatilemain.cpp|18|error: could not convert ‘mi_ref’ to ‘bool’|
        ||=== Build finished: 1 errors, 0 warnings ===|

        Ok,总结:

    while(cin >> str)
        ivec.push_back(str);

        while 判断时,会调用了 operator void*() 这个函数,是否返回 0 取决于 fail 这个函数。当在缓冲区读入数据的时候,如果出现

        异常,这些异常通过一些变量记录下来,而这些变量会左右 fail 的返回值。

        CTRL+Z -> 引发异常 -> 记录异常 -> fail() 返回true-> operator void*() 返回 0 -> while结束

        在 cplusplus.com 中对这个函数的解释这样的:

        operator void * () const;
        Convert to pointer
        A stream object derived from ios can be casted to a pointer. This pointer is a null pointer if either one of the error

        flags (failbit or badbit) is set, otherwise it is a non-zero pointer.
        The pointer returned is not intended to be referenced, it just indicates success when none of the error flags are set.

        (可以看出和我的理解是一致的)

      6,关于数据类型bool;

        a,ture ,  false;

        b,当整型对待(“1“);

          bool    found = ture;

          int      a;

          a = 1 + fount;

        c,指针可以当做bool对象进行操作;

      7,关于间接访问、自增相遇时的先后顺序问题;

        i,    (* a ++)  : 先后自增再间接访问;后自增的优先级高于间接访问;

        ii,    (* ++ a)  : 先前自增再间接访问;

        iii,   (++ * a)  : 先间接访问再前自增;

  • 相关阅读:
    深入理解Linux修改hostname
    逆水行舟,不进则退
    TNS-12541: TNS:no listener TNS-12560 TNS-00511: No listener
    Linux Tomcat 6.0安装配置实践总结
    Database 'xxx' cannot be upgraded because it is read-only or has read-only file Make the database or files writeable, and rerun recovery.
    Tomcat启动找不到JRE_HOME的解决方法
    ORACLE触发器判断是否更新了某个字段
    MS SQL错误:SQL Server failed with error code 0xc0000000 to spawn a thread to process a new login or connection. Check the SQL Server error log and the Windows event logs for information about possible related problems
    MS SQL 错误:The operation could not be performed because OLE DB provider "SQLNCLI10" for linked server "test" was unable to begin a distributed transaction.
    ORA-01078: failure in processing system parameters & LRM-00109: could not open parameter file
  • 原文地址:https://www.cnblogs.com/richard-c-java/p/3297774.html
Copyright © 2020-2023  润新知