More Effective C++ 第一部分 基础议题
Posted zhangqixiang5449
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了More Effective C++ 第一部分 基础议题相关的知识,希望对你有一定的参考价值。
1.仔细区别pointers和references
当你知道你需要指向某个东西,而且绝不会改变其指向其他的东西,或当你实现一个操作符而语法需求无法由pointer达成,你就应该选用reference.任何其他时候,请使用pointers.
指向NULL
一个reference必须代表某个对象,即不可为NULL。而pointer 可以。若使用reference将意味着不再考虑reference成为NULL的可能性。也就意味着使用reference可能比pointer更有效率,因为不需要考虑NULL的问题。
由于该特性,C++要求reference必须有初值,而pointer并无此要求。
重新赋值
pointer可以重新赋值,而reference不可以,reference总是指向最初获得的那个对象。(类似const)
如果希望在不同时刻指向不同对象,那么只能使用pointer。若希望一旦代表了某个对象就不能再改变,就应当选用reference。
其他使用reference的情况
最常见的例子就是operator[],例如:
vector<int> v(10);
v[5] = 10;//operator[]返回reference
*v[5] = 10;//operator[]返回pointer
若使用pointer可能会误以为vector内存的是指针。
2.最好使用C++转型操作符
新式转型操作符用途更加专一,并且更能表明程序员的意图(例如使用const_cast),也更容易被机器和人类识别。并提供安全性(dynamic_cast)。还提供一些旧式转型无法提供的功能(reinterpret_cast)。
reinterpret_cast:用来转换函数类型指针,不具可移植性,非十分迫不得已,不应使用。
typedef void (*FuncPtr)();
FuncPtr funcPtrArray[10];//返回类型为void的函数指针数组
int doSomething();//返回类型为int
funcPtrArray[0] = reinterpret_cast<FuncPtr>(&doSomething);
3.绝不要以多态方式处理数组
Base类型数组 array[i] 代表的是 *( array + i * sizeof(Base) )
,若将Base类型的数组以多态的形式指向Derived类型的对象数组,那么编译器的寻址方式依然是使用sizeof(Base),将导致未定义的结果。例如:
#include <iostream>
class Base
public:
int a = 1;
;
class Derived: public Base
public:
int b = 2;
;
//该函数接受Base类型的指针,并输出其内容。
void func(const Base array[],int num)
for (int i = 0; i < num; i++)
std::cout<<array[i].a<<" ";
std::cout<<std::endl;
int main(int argc, const char * argv[])
Base baseArray[10];
Derived derivedArray[10];
func(baseArray,10);//传入Base类型数组,没问题
func(derivedArray, 10);//传入Derived类型数组,并未报错,但结果与期望的不一致。
return 0;
该程序输出
1 1 1 1 1 1 1 1 1 1
1 2 1 2 1 2 1 2 1 2
Program ended with exit code: 0
我们可以看到使用多态的方式处理数组带来的错误,我们也可以根据输出结果来推断编译器解释array[i]时使用的是 *( array + i * sizeof(Base) )
,而不因为array是其派生类类型而做出改变。
4.非必要不提供default constructor
default constructor为参数为空的构造函数。缺乏default constructor将会带来2个缺点:
1.无法产生数组。因为没有方法可以为数组中的对象知道constructor变量。
2.不适用于许多template-base container classes。
但是强行提供default constructor将会带来程序质量的下降,比如一个需要ID初始化的类,若提供default constructor便要在程序中检查其ID有无被正确初始化,使得效率降低,代码量增加。
以上是关于More Effective C++ 第一部分 基础议题的主要内容,如果未能解决你的问题,请参考以下文章