"C++ Primer Plus" tenth reading notes - class and dynamic memory allocation

Chapter 12 Classes and Dynamic Memory Allocation

  1. Static member variables cannot be initialized in a class declaration, because the declaration describes how to allocate memory, but does not allocate memory. Initialization can be done with a separate statement outside of the class declaration because static class members are stored separately, not part of the object. Note: Static members are declared in the class declaration and initialized in the file containing the class method. The scope operator is used during initialization to indicate the class to which the static member belongs. But if the static member is of type integer or enumeration const, it can be initialized in the class declaration.

  2. When an object is used to initialize another newly created object, the compiler will automatically generate a copy constructor because it creates a copy of the object. The prototype of the copy constructor is: classname (const classname &);

  3. C++ automatically provides the following functions : ① default constructor, if no constructor is defined ② copy constructor, if not defined ③ assignment operator, if not defined ④ default destructor, if not defined ⑤ address operator , if not defined

  4. When to call the copy constructor: When a new object is created and initialized to an existing object of the same kind, the copy constructor will be called. For example, assuming motto is an object of class stringbad, the following four declarations will all call the copy constructor:

  ①stringbad ditto(motto);②stringbad metto=motto;③stringbad also=stringbad(motto);④stringbad *p=new stringbad(motto); where ②③ may use the copy constructor to directly create metto and also, or use the copy constructor to generate A temporary object, then assign the contents of the temporary object to metto and also, depending on the implementation.

  5. Whenever a program makes a copy of an object, the compiler will use the copy constructor. Specifically, the copy constructor is used when a function is passed by value (creates a copy of the original variable) or when the function returns an object. The copy constructor is also used when the compiler generates temporary objects.

  6. The default copy constructor copies the non-static constructors one by one ( shallow copy ), copying the value of the member. If the member is itself a class object, the copy constructor of this class will be used to copy the member function. Static functions are not affected.

  7. If the class contains pointer members initialized with new, a copy constructor should be defined to copy the pointed data instead of the pointer, which is also called deep copy . Shallow copy, also called member copy, just copies the pointer value without digging too deep to copy the structure the pointer refers to.

  8. Assignment operator : C++ allows assignment of class objects, which is achieved by automatically overloading the assignment operator for the class. The prototype of this operator is as follows:

  classname & classname::operator=(const classname &);

  9. When to use the assignment operator: When assigning an existing object to another object, the overloaded assignment operator will be used. Note: Initialization (creating a new object) always calls the copy constructor, and using the = operator may also call the assignment operator. The assignment operator does not create a new object.

  10. Similar to the copy constructor, the implicit implementation of the assignment operator also copies members one by one (shallow copy). If the member is itself a class object, the program copies the member using the assignment operator defined for that class. For problems caused by the inappropriate default assignment operator, the solution is to provide an assignment operator (which does a deep copy) definition . Its implementation is similar to the copy constructor, but there are some differences. one example:

  stringbad & stringbad::operator= (const stringbad & st)

  {

    if(this==&st)  // 检查自我复制

      return *this;

    delete [] str;  // 释放成员指针以前指向的内存

    len=st.len;

    str=new char[len+1];

    std::strcpy(str,st.str);

    return *this;    // 返回一个指向调用对象的引用

  }

  11、由于静态成员函数不与特定的对象相关联,因此只能使用静态数据成员。

  12、重载>>操作符:

  istream & operator>>(istream & is,string & st)

  {

    char temp[10];  // 假设输入的字符数不多于10

    is.get(temp,10);  // 如果由于某种原因(如到达文件尾,或读取的是一个空行),导致输入失败,istream对象的值将置为false

    if(is)

      st=temp;

    while(is&&is.get()!='\n')  // 丢弃多余的字符

      continue;

    return is;

  }

  13、if(!cin)检测空行!!

  14、可以在一个构造函数中使用new来初始化指针,而在另外一个构造函数中将指针初始化为空(NULL或0),这是因为delete(无论带中括号还是不带)可以用于空指针。

  15、如果函数返回传递给他的对象,可以通过传递引用来提高方法的效率。返回对象将调用复制构造函数,而返回引用不会。

  16、重载操作符<<函数,返回类型必须是ostream &,而不能仅仅是ostream。如果返回类型ostream,将要求调用ostream类的复制构造函数,而ostream没有公有的复制构造函数。

  17、总结:如果方法或函数返回局部对象,则应返回对象而不是指向对象的引用。在这种情况下,将使用复制构造函数来生成返回的对象。如果方法或函数返回一个没有公有复制构造函数(如ostream类)的对象,它必须返回一个指向这种对象的引用。最后,有些方法和函数(如重载的赋值操作符)可以返回对象,也可以返回指向对象的引用,在这种情况下,应首选引用,因为其效率高。

  18、成员初始化列表:classname::classname(int n,int m):mem1(n),men2(0),men3(n*m+2){ //....}从概念上说,这些初始化工作是在对象创建时完成的,此时还未执行括号中的任何代码。对于简单数据成员,使用成员初始化列表和在函数体中使用赋值没有什么区别。不过,对于本身就是类对象的成员来说,使用成员初始化 列表效率更高。注:①这种格式只能用于构造函数。②必须用这种格式初始化非静态const数据成员。③必须用这种格式初始化引用数据成员。

  19、在类中嵌套结构和类声明: 在类声明中声明的结构、类或枚举被称为是被嵌套在类中,其作用域为整个类。这种声明不会创建数据对象,而只是指定了可以在类中使用的类型。如果声明是在类的私有部分进行的,则只能在这个类中使用被声明的类型;如果声明是在公有部分进行的,则可以从类的外部通过作用域解析操作符使用被声明的类型。例如:如果Node是在Queue类的公有部分声明的,则可以在类的外面声明Queue::Node类型的变量。

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324837229&siteId=291194637