《C++ Primer》读书笔记

1、在C++中理解“初始化不是复制”是必要的。

2、对于类类型的对象来说,定义如何初始化的函数称为构造函数。(构造函数用来初始化类类型的变量)

3、和其他函数一样,构造函数能接受多个参数。一个类可以定义几个构造函数,每个构造函数必须接受不同数目或者不同类型的参数。

4、可以通过使用extern关键字声明变量名而不定义它。不定 义变量的声明包括对象名、对象类型和对象类型前的关键字extern:  extern int iextern声明不是定义,也不分配存储空间。它只是说明变量定义在程序的其他地方。程序中变量可以声明多次,但只能定义一次。

5、引用就是对象的另一个名字。引用是一种复合类型,通过在变量名前添加“&”符号来定义。要理解的重要概念是引用只是对象的另一名字。

6、枚举      

       enum open_modes{input,output,append};

       默认地,第一个枚举成员赋值为0,后面的每个枚举成员赋的值比前面的大1

7、如何定义简单的类?

    从操作开始设计类。定义类时,通常先定义该类的接口,即该类所提供的操作。通过这些操作,可以决定该类完成其功能所需要的数据,以及是否需要定义一些函数来支持该类的实现。

8、定义数据成员时,只能定义其类型和变量名,不能进行初始化。

9、文件用于声明而不是用于定义。但是有三个例外:头文件可以定义类、值在编译时就已知道的const对象和inline函数。这些实体可在多个源文件中定义,只要每个源文件中的定义是相同的。

10头文件一般包含类的定义,extern型变量的声明和函数的声明。头文件的正确使用能够来两个好处:保证所有文件使用给定实体的同一声明;当声明需要修改时,只有头文件需要更新。

11、设计头文件时,应使其可以多次包含在同一源文件中,这一点很重要。我们必须保证多次包含同一头文件不会引起该头文件定义的类和对象被多次定义。使得头文件安全的通用做法,是使用预处理器定义头文件保护符。头文件保护符用于避免在已经见到头文件的情况下重新处理该头文件的内容。

12string类型支持长度可变的字符串,vector可用于保存一组指定类型的对象。

13member function definition looks like a ctor, but name does not match enclosing class

这个错误是因为除构造函数外所有的类成员函数都要有返回值的类型,如果没有返回值,就在函数定义前面加上void,这个编译错误就可以解决

14vector不是一种数据类型,而只是一个类模板,可用来定义任意多种数据类型。

15newdelete表达式也可用于动态创建和释放单个对象,动态创建对象时,只需指定其数据类型,而不必为该对象命名。取而代之的是,new表达式返回指向新创建对象的指针,我们通过该指针来访问此对象:

       int i;

       int *pi = new int;

16、正如我们几乎总是要初始化定义为变量的对象一样,在动态创建对象时,几乎总是对它做初始化也是一个好办法。

17、对于提供了默认构造函数的类类型(如string),没有必要对其对象进行值初始化:无论程序员是明确地不初始化还是要求进行值初始化,都会自动调用其默认构造函数初始化该对象。而对于内置类型或没有定义默认构造函数的类型,采用不同初始化方式则有显著地差别:

       int *pi = new int;         //pi 指向一个未进行初始化的int型变量

       int *pi = new int();          //pi指向一个初始化为0int型变量

18、值初始化的()语法必须置于类型名后面,而不是变量后。

19、动态创建的对象用完后,程序员必须显式地将该对象占用的内存返回给自由存储区。C++提供了delete表达式释放指针所指向的地址空间。delete pi;//该命令释放pi指向的int型对象所占用的内存空间。

20、一旦删除了指针所指向的对象,立即将指针置为0,这样就非常清楚地表明指针不再指向任何对象。

21、与其他常量一样,动态创建的const对象必须在创建时初始化,并且一经初始化,其值就不能再修改。

       const int *pci = new const int(1024);

上述new表达式返回指向intconst对象的指针。与其他const对象的地址一样,由于new返回的地址上存放的是const对象,因此该地址只能赋给指向const的指针。

22、每一个程序在执行时都占有一块可用的内存空间,用于存放动态分配的对象,此内存空间称为程序的自由存储区(free store)或堆(heap.C语言程序使用一对标准库函数mallocfree在自由存储区中分配存储空间,而C++语言则使用newdelete表达式实现相同的功能。

23、在switch语句中,存在一个普遍的误解:以为程序只会执行匹配的case标号相关联的语句。实际上,程序从该点开始执行,并跨越case边界继续执行其他语句,直到switch结束或遇到break语句为止。——为了避免继续执行其后续case标号的内容,程序员必须利用break语句清楚地告诉编译器停止执行switch中的语句。在大多数情况下,在下一个case标号之前的最后一条语句是break

24、对于switch结构,漏写break语句是常见的错误。

25default标号提供了相当于else子句的功能。如果所有的case标号与switch表达式的值都不匹配,并且default标号存在,则执行default标号后面的语句。

26、哪怕没有语句要在default标号下执行,定义default标号仍然是有用的。定义default标号是为了告诉它的读者,表明这种情况已经考虑到了,只是没什么必要执行的。

27

//7.2节示例

#include

using namespace std;

void reset(int *ip)

{

       *ip = 0;

       ip = 0;

}

 

int main()

{

       int i = 42;

       int *p = &i;

       cout<<"i: "<<*p <<'\n';

       reset(p);

       cout<<"i: "<<*p<

       return 0;

}

27、通常,将数组形参直接定义为指针要比使用数组语法定义更好。这样就明确地表示,函数操纵的是指向数组元素的指针,而不是数组本身。由于忽略了数组的长度,形参定义中如果包含了数组长度则特别容易引起误解。

28、编译器会忽略为任何数组形参指定的长度。

29、不需要修改数组形参的元素时,函数应该将形参定义为指向const对象的指针:

       void f(const int*)

30static局部对象:确保不迟于在程序执行流程第一次经过该对象的定义语句时进行初始化。这种对象一旦被创建,在程序结束前都不会被撤销。当定义静态局部对象的函数结束时,静态局部对象不会撤销。在该函数被多次调用的过程中,静态局部对象会持续存在并保持它的值。

例如:下面这个函数计算了自己被调用的次数:

       size_t count_calls()

       {

              static size_t ctr = 0;   //value will persist across calls

              return ++ctr;

       }

       int main()

       {

              for(size_t i=0;i!=10;++i)

                     cout<

              return 0;

       }

 

31、内联函数应该在头文件中定义,这一点很特别,不同于其他的函数。

32、在头文件中加入或修改内联函数时,使用了该头文件的所有源文件都必须重新编译。

33、关于类的成员函数,函数原型必须在类中定义,但是函数体既可以在类中定义,也可以在类外定义。

34、编译器隐式的将类内定义的成员函数当做内联函数。

35、类的成员函数可以访问该类的private成员。

你可能感兴趣的:(C++,学习总结,编程)