Effective C++ T03:尽可能使用const

38 篇文章 0 订阅
31 篇文章 2 订阅

Effective C++学习笔记总链接

改善程序与设计的55个具体做法学习笔记-每日1条


条款03:尽可能使用const

【技巧】

1.将某些东西声明为const 可帮编译器侦测出错误用法。

2. const尽可能施加于任何作用域内的对象,函数参数,函数返回类型,成员函数本体。

3. 编写程序时,应该使用“概念上的常量性”(mutable)

4. 当const和non-const 成员函数有着实质等价的实现时,令non-const 版本调用const 版本可避免代码重复。


const 指针

char greeting[] = "Hello";
const char* p = greeting; // const data 
char const * p = greeting; // const data ,与上式意义相同
char* const p = greeting; // const pointer
const char* const p = greeting; // const pointer const data

const 出现在星号的左边,表示被指物是常量。
const 出现在星号的右边,表示指针自身为常量。
const 出现在星号的两边,表示被指物和指针两者都为常量。

const STL迭代器

迭代器的作用就像个T* 指针,const 迭代器相当于T* const指针,代表迭代器不得指向不同的东西。如果希望迭代器所指的东西值不变,需要const_iterator

std::vector<int> vec;
...
const std::vector<int>::iterator iter =  // iter 相当于 T* const
vec,begin();
*iter = 10; // ok
iter++; // error, iter是const
...
std::vector<int>::const_iterator citer = // citer 相当于 const T* 
vec,begin();
*citer = 10; // error, *citer是const
citer++; // ok		

函数返回值为const

令函数返回一个常量值,往往可以降低因客户错误而造成的意外。

class Rational{...};
const Rational opterator* (const Rational&, const Rational&);
...
Rational a,b,c;
(a*b) =c ;// 错误

除非你需要改动参数或local const对象,否则请将他们声明为const.

const 成员函数

const成员函数,是为了确认该成员函数可作用于const对象

第一:使得class接口比较容易被理解。哪个函数可以改动对象内容,而哪个函数不行。
第二:使操作const对象成为可能,这是编写高效代码的关键。

改善C++程序效率的一个根本办法是以 pass-by-reference-to-const 方式传递对象。(条款20)

两个成员函数如果只是常量性不同,可以被重载。

const char& operator[](std::size_t position) const // operator[] for const对象
char& operator[](std::size_t position) // operator[] for non-const对象

const成员函数mutable

在const成员函数中,mutable 成员变量可以被更改

class CTextBlock{
public:
	...
	std::size_t length() const;
private:
	char* pText;
	mutable std::size_t textLength; //这些成员变量可能总是会被改变,
	mutable bool lengthIsValid;     //即使在const成员函数中。
}

std::size_t CTextBlock::length() const
{
	if(!lengthIsValid){
		textLength = std::strlen(pText);
		lengthIsValid = true;
	}
	return textLength;
}

在const和non-const成员函数中避免重复

上述两个版本的operator[],可能存在代码重复

真正该做的是实现operator[] 的机能一次并使用它两次。也就是令其中一个调用另一个。这就促使我们将常量性转除

转型是个糟糕的想法(条款27),但是代码重复更加糟糕。

令non-const版本 调用 const 版本

因此,令non-const operator[] 调用其const 兄弟是一个避免代码重复的安全做法。即使过程中需要一个转型动作。

class TextBlock{
public:
	...
	const char& operator[](std::size_t position) const // operator[] for const对象,一如既往
	char& operator[](std::size_t position) // operator[] for non-const对象
	{
		//将op[] 返回值的const转除为*this加上const调用const op[]
		// 两次转型,下面解释
		return const_cast<char&>(static_cast<const TextBlock&>(*this)[position]);
	}
}

用non-const op[] 调用其const兄弟,如果non-const op[] 内部只是单纯的调用operator[],会递归调用自己

我们必须明确指出调用的是const op[],但C++缺乏直接的语法可以那么做。

因此,我将*this 从其原型 TextBlock& 转化为 const TextBlock&

使用转型操作为它加上const!

这里两次转型:
第一次用来为*this 添加const(这使接下来调用operator[] 时得以调用const版本)
第二次则是从const op[] 的返回值中移除 const

令const版本调用non-const版本是一种错误行为

const 成员函数承诺绝不改变其对象的逻辑状态,non-const 成员函数却没有这种承诺。
如果const函数调用non-const函数,就会冒风险:你曾经承诺不改动的那个对象被改动了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值