- c++的函数传递引用与指针的区别。
c++ primer解释引用与指针的区别:
共同点: 虽然使用引用和指针都可间接访问另一个值
不同点: 1.引用总是指向某个对象:定义引用时没有初始化会编译错误。
2.赋值行为的差异:给引用赋值修改的是该引用所关联的值,而并不是使引用和另一个对象关联。引用一经初始化,就始终指向同一个特定对象(这就是为什么引用必须在定义时初始化的原因)。给指针赋值修改的是指针对象本身,也就是使指针指向另一个对象。指针可以在不同时刻指向不同的对象(只要保证类型匹配)
- c#类似于类型安全的指针,可以避免非法内存访问和内存泄露。和c++中的引用概念完全不同,c++中的引用只是一个别名,和c#的ref函数参数传递方式差不多,不过c#检查更严格(实参传递前要赋值,实参形参都要显式声明为ref)
- 指针常量和指向常量的指针
typedef string *pstring;
const pstring cstr;
这两条语句相当于string *cosnt cstr;(而不是const string *cstr )。
这有点像p86 const_iterator对象(指向const的iterator)与const的iterator(iterator不可作为左值,但能修改它指向的对象)区别。iterator实现机理应该就是一个指针
- 越界问题
自问自答:.net有CLR,其中有异常检查功能。CLR会运行时抛出异常IndexOutOfRangeException
- c++常用类型
difference_type p87
size_t p90:相当于unsigned int,在<cstddef>中定义
NULL p103:预处理器变量,相当于0,在<cstdlib>中定义
ptrdiff_t p107:在<cstddef>中定义
- 通过引用传递数组(p208)
和其他类型一样,数组形参可声明为数组的引用。如果形参是数组的引用,编译器不会将数组实参转化为指针,而是传递数组的引用本身。在这种情况下,数组大小成为形参和实参类型的一部分。编译器检查实参的大小与形参的大小是否匹配
- 默认构造函数(P392)
默认构造函数指的就是无参构造函数(无论是系统自动生成的,还是用户自己编写无参构造函数)。如果用户没有定义任何构造函数,编译器会自动生成一个默认构造函数。如果用户定义了构造函数(哪怕一个),编译器就不会再生成默认构造函数。比如:如何某类只定义了一个带实参的构造函数,但没有定义无参构造函数,则该类就没有无参构造函数
- 内联函数(p221-223,373,374)
内联函数应该在头文件中定义,这一点不同于其他函数。像其他inline一样,inline成员函数的定义必须在调用该函数的每个源文件中是可见的。不在类定义体内定义的inline成员函数,其定义通常应放在有类定义的同一头文件中。
- 构造函数初始化(p387-390)
1)因为如果有类类型数据成员时,使用构造函数初始化列表效率更高,因为如果在构造函数体内对数据成员赋值之前,编译器会隐式使用默认构造函数来初始化类类型数据成员。
2)有些情况只能在构造函数初始化列表中进行初始化,对于这样的成员,在构造函数体中对它们赋值不起作用。这些情况有:没有默认构造函数的类类型成员,const成员,引用类型成员
构造函数初始化列表仅指定用于初始化成员的值,并不指定这些初始化执行的次序。成员被初始化的次序是定义成员的次序。按照与成员声明一致的次序编写构造函数初始化列表是个好主意。此外,尽可能避免使用成员来初始化其他成员。
(1)new自动计算要分配类型的大小,不使用sizeof运算符,比较省事,可以避免错误。
(2、它自动地返回正确的指针类型,不用进行强制指针类型转换(malloc返回void*)。
(3)可以用new对分配的对象进行初始化。
此外,free和delete也是有区别的,他们都负责释放空间,但是free 在释放之前不调用析构函数,而delete 在释放内存前调用析构函数析构对
p117,150
可以用单个实参来调用的构造函数定义了从形参类型到该类类型的一个隐式转换
复制构造函数是一种特殊构造函数,具有单个形参,该形参(常用const修饰)是对该类型的引用
when什么时候发生调用复制构造函数:
(1)根据另一个同类型的对象显式或隐式初始化一个对象。(有三种情况:1)当定义一个新对象并用一个已定义同类型对象对它进行初始化时,将显式使用复制构造函数。但2)赋给它一个临时对象或3)一个实参(具有可以隐式转化的构造函数)时,在vs2008并不会调用复制构造函数,编译器进行了优化相当于直接初始化,前提是复制构造函数不是私有的并且隐式转化的构造函数没有声明为explicit),所以还是尽量用直接初始化
(2)复制一个对象,将它作为实参传给一个函数
(3)从函数返回时复制一个对象
(4)初始化顺序容器中的元素
c++ primer指出的第5条根据元素初始化式列表初始化数组元素,vs2008进行了优化,不会调用复制构造函数,相当于直接初始化。但有前提条件,理由同上
.赋值操作符(p411)
What:
重载赋值操作符,只有一个同类型对象(通常为const引用)的形参,返回该类型的引用
什么时候发生调用赋值操作符:
只有定义类对象的同时赋值已定义的同类型对象(不是临时对象,或隐式转换的对象,他们会被vs2008优化)才会调用复制构造函数
只有定义类对象和初始化类对象分为两条语句才会调用赋值操作符
How:
三法则(rule of three):如果类需要析构函数,则它也需要赋值操作符和赋值构造函数。三者捆绑在一起
构造函数初始化列表仅指定用于初始化成员的值,并不指定这些初始化执行的次序。成员被初始化的次序是定义成员的次序。按照与成员声明一致的次序编写构造函数初始化列表是个好主意。此外,尽可能避免使用成员来初始化其他成员。
- new与malloc的区别以及new的使用注意事项
(1)new自动计算要分配类型的大小,不使用sizeof运算符,比较省事,可以避免错误。
(2、它自动地返回正确的指针类型,不用进行强制指针类型转换(malloc返回void*)。
(3)可以用new对分配的对象进行初始化。
此外,free和delete也是有区别的,他们都负责释放空间,但是free 在释放之前不调用析构函数,而delete 在释放内存前调用析构函数析构对
p117,150
- 隐式类型转换(p393)
可以用单个实参来调用的构造函数定义了从形参类型到该类类型的一个隐式转换
- 复制构造函数(p406)
复制构造函数是一种特殊构造函数,具有单个形参,该形参(常用const修饰)是对该类型的引用
when什么时候发生调用复制构造函数:
(1)根据另一个同类型的对象显式或隐式初始化一个对象。(有三种情况:1)当定义一个新对象并用一个已定义同类型对象对它进行初始化时,将显式使用复制构造函数。但2)赋给它一个临时对象或3)一个实参(具有可以隐式转化的构造函数)时,在vs2008并不会调用复制构造函数,编译器进行了优化相当于直接初始化,前提是复制构造函数不是私有的并且隐式转化的构造函数没有声明为explicit),所以还是尽量用直接初始化
(2)复制一个对象,将它作为实参传给一个函数
(3)从函数返回时复制一个对象
(4)初始化顺序容器中的元素
c++ primer指出的第5条根据元素初始化式列表初始化数组元素,vs2008进行了优化,不会调用复制构造函数,相当于直接初始化。但有前提条件,理由同上
.赋值操作符(p411)
What:
重载赋值操作符,只有一个同类型对象(通常为const引用)的形参,返回该类型的引用
什么时候发生调用赋值操作符:
只有定义类对象的同时赋值已定义的同类型对象(不是临时对象,或隐式转换的对象,他们会被vs2008优化)才会调用复制构造函数
只有定义类对象和初始化类对象分为两条语句才会调用赋值操作符
How:
三法则(rule of three):如果类需要析构函数,则它也需要赋值操作符和赋值构造函数。三者捆绑在一起
- 空白字符:指的是空格、换行符、制表符