总结:细节问题(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)  : 先间接访问再前自增;

原文地址:https://www.cnblogs.com/richard-c-java/p/3297774.html