栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

Effective C++学习记录

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Effective C++学习记录

Effective C++
  • 1 让自己习惯C++
    • 条款01:视C++为一个语言联邦
    • 条款02:尽量以const,enum,inline替换#define
    • 条款03:尽可能使用const
    • 条款04:确定对象被使用前已先被初始化

Effictive C++ 学习记录

1 让自己习惯C++

Accustoming Yourself to C++

条款01:视C++为一个语言联邦

View C++ as a federation of languages

C++ 可分为四个主要的次语言

  • C 。 C++的区块、语句、预处理器、内置数据类型、数组、指针等来自于C。
  • Object-Oriented C++。面向对象,类、封装、继承、多态、虚函数等。
  • Template C++。泛型编程。
  • STL。标准模板库,对容器、迭代器、算法以及函数对象进行配合和协调。

条款02:尽量以const,enum,inline替换#define

Perfer consts,enums,and inlines to #define

意为“宁愿使用编译器,替换使用预处理器”

当写下这样的语句:

#define PI 3.14

预处理器会将代码中的“PI”替换成“3.14”,“PI”不会进入记号表中,如果出现错误,追踪不知了来源的数字会浪费时间。

而且使用#define可能会造成语句混乱,当写下下面的语句时,由于define是整体替换,可能会改变原有的语句意思,例如,原本b的值为(3+13)×3=48,但是现在变成3+13×3=42。

#define a 3+13

int main(){
	int b = a*3;
	return 0;
}

为了解决#define带来的问题,可以使用常量const替换宏,这样就可以被编译器看到,从而进入记号表中。

const double PI = 3.14;

用常量const替换#define时,需要注意两种特殊情况:

  1. 定义常量指针
    常量定义通常被放在头文件中,因此有必要将也指针声明为const,即,
const std::string stringname("BeiJing"); 

注:string对象会比char*更好点

  1. class 专属常量
    为了使常量的作用域限制在类中,必须使其成为一个成员;同时保证此常量至多只有一份,必须使其成为一个static成员。
class GamePlayer{
private:
	static const itn NumTurns = 5;// 常量声明式
	int scores[NumTurns];// 使用该常量
};

注意,这里是声明并非定义!
如果不取NumTurns的地址,你可以不用提供定义式,但是如果取地址的话,就需要让编辑器看到一个定义式。

const int GamePlayer::NumTurns;  // 定义式  无需设初值

注:一个对象可以声明多次,但只有一次定义!

初值可以放在定义式上,也可以放在声明式上(如果编辑器允许的话)。

当然,你也可以使用enum(枚举)。

class GamePlayer{
private:
	enum {NumTurns = 5};
	int scores[NumTurns];// 使用该常量
};

取enum的地址也不合法(有点像#define)

inline函数也可以用来解决#define带来的糟糕麻烦
例如,

template    // 模板
inline void callWithMax(const T& a , const T& b){
	f(a>b:a?b);
}

小结:

  • 对于单纯常量,最好以const或者enums替换#define
  • 对于形似函数的宏,最好改用inline函数替换#define

条款03:尽可能使用const

Use const whenever possible

const奇妙之处在于,编辑器会强制实施它所允许的语义约束(指定一个不可被改动的对象)。

当修饰指针时,关键字const位于星号*的左边,表示被指物(所指对象)是常量(被指对象的值不能被改变);如果位于右边,则指针本身是常量(不能改变指针指向)。

关于迭代器

迭代器是根据指针塑膜出来的,就像一个T*指针,所以对迭代器进行约束就相当于对指针进行约束。

  • 如果希望迭代器不能指向不同的东西,但是指向的值可以改动,即相当于声明一个 T* const 指针;
  • 如果希望迭代器所指的东西不可改动,即相当于声明一个const T*指针,需要使用 const_iterator
std::vector vec;

const std::vector::iterator iter = ver.begin(); // iter 相当于T* const 
*iter = 10;   // 指向对象的值可以改变
iter++;  // 错误 自身不能改变

std::vector::const_iterator citer = ver.begin(); // citer 相当于const  T* 
*citer = 10;   // 错误  指向对象的值不可以改变
citer++;  // 自身能改变

如果有需要改动参数或者local对象,否则请将它们设为const。

两个流行概念

  • bitwise constness
    const成员函数不能更改对象内任何non-static对象,但是可以用mutable关键字释放约束
  • logical constness
    const成员函数可以修改,但是要在客户端侦测不出的情况下?

小结:

  • 将某些对象设为const
  • 编辑器强制实施bitwise constness,但是你需要有自己的逻辑
    令non-const版本调用const(实质等价实现)版本可避免代码重复
条款04:确定对象被使用前已先被初始化

Make sure that objects are initialized before they’re used

最佳处理方法
永远在使用对象之前将它初始化

对于类对象,可以使用初始化列表对成员进行初始化

class People{
private:
	int theAge;
	string theName;
public:
	People(int age,string name):theAge(age),theName(name){}
};

注意是设初值,而不是赋值,尤其是成员变量是const和引用,必须设初值。

两个成员变量的初始化带有次序性;

小结:

  • 为内置型对象进行手工初始化
  • 构建函数最好使用初始化列表
  • 为免除“跨编译单元之初始化次序”的问题,请以local static 对象替换non-local static对象
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/961045.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号