函数参数传递的方式
值传递、指针传递和引用传递
它们之间的区别是什么呢?
- 值传递传递的是实际参数一个副本;
- 指针传递时,函数体内只要指针值的变化,会影响值的变化,但是只有指针的变化,不会引起变化;
- 引用传递,对形参的操作等同于对实参的操作。
函数返回值
- 全局变量,局部静态变量,局部动态分配变量都可以作为函数返回值。
- 局部对象或者局部变量的指针或引用不能作为函数的返回值。
为什么呢?
- 全局变量就不讲了,因为它具有全局作用域;
- 静态局部变量,虽然具有局部作用域,但是它一直存在直到程序运行结束才销毁;
- 局部动态分配的变量,分配在堆中,堆中分配的内存需要人为的释放,不释放的话,它是一直存在的;
- 对于局部对象或变量,它们存在于栈中,栈中的变量都是用完就自动释放的,之后局部变量或对象就不存在与内存中,会出现未定义或者空值的错误。
内联函数
- 关键字inline必须与函数定义体放在一起才能使函数称为内联,仅放在函数声明前面不起任何作用;
- 内联函数是在编译阶段展开的;
- 使用类的引用或指针调用虚函数,虚函数不允许内联,因为虚函数的调用时在运行时确定的。
- 使用类对象调用虚函数时,虚函数可以内联,因为编译器知道对象的确定类型。
字符串常量容易出错的地方
char str1[] = "abcd";
char str2[] = "abcd";
const char str3[] = "abcd";
const char str4[] = "abcd";
const char *str5 = "abcd";
const char *str6 = "abcd";
char *str7 = "abcd";
char *str8 = "abcd";
cout << ( str1 == str2 ) << endl;
cout << ( str3 == str4 ) << endl;
cout << ( str5 == str6 ) << endl;
cout << ( str7 == str8 ) << endl;
str1、str2、str3、str4是数组变量,他们各自有内存空间;字符数组作为局部变量被存储在栈区;而str5、str6、str7、str8是指针,指向相同的区域,“adcd”被存储在静态数据区。
类的初始化
- 成员类型是没有默认构造函数的类、const成员或引用类型的成员都必须使用初始化列表;
- 初始化成员时,,是按照声明的顺序进行初始化的。
- 变量初始化的顺序:基类的静态变量或全局变量,派生类的静态或全局变量,基类的成员变量,派生类的成员变量。
空类
- 声明一个空类,编译器会自动生成默认构造函数、默认拷贝构造函数、默认拷贝赋值操作符、默认析构函数。
- 空类的大小为1个字节。
- 类的大小为类的非静态成员数据或函数的类型大小之和。与类中的构造函数,析构函数以及其他的成员函数无关。
虚函数
一般有虚函数类都有一个虚函数表,里面包含所有类的虚函数,类中有一个虚指针就指向这个虚函数表。
- 对于B类继承A类,类A中的私有成员仍在类B中占有内存。
- 虚继承,有一个指向虚基类的指针。
- 多重继承,会出现多个指向基类的虚函数表。
类中的const限定符
- const常量必须在构造函数初始化列表中初始化,不可以在构造函数函数体内初始化。
- const成员函数,不允许修改类的数据成员;
- const对象不可以调用非const成员函数。
- 非const对象既能访问const成员函数,也能访问非const成员函数。
类中的static限定符
- 静态数据成员是该类所有对象共有的,所有对象共享这个静态数据成员。
- 静态数据成员需要在类外定义。
- 普通的成员函数一般都隐藏了一个this指针,this指针指向类的对象本身,因为普通成员函数总是具体的属于某个类的具体对象的。通常情况下,this指针是缺省的、但是与普通函数相比,静态成员函数由于不是与任何的对象相联系,因此它不具有this指针
- 静态成员函数是属于类的,即不与该类的任何对象想联系,而this指针指向类的具体对象,因此静态成员函数没有this指针。
4.静态成员函数无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,它只能调用其余的静态成员函数。 - 非静态成员函数可以任意地访问静态成员函数和静态数据成员;