const允许你指定一个语义约束,告诉编译器不改动某个对象
STL的迭代器就是以指针为根据塑造出来的,声明迭代器为const就像声明指针为const一样,即,你可以修改迭代器指向的东西的值,但这个迭代器不可以指向不同
的东西。如果你希望迭代器所指的东西不可改动,则需要 const_iterator:
为函数返回值加上const
用以阻止这样的暴行
尽管难以想象为什么会有人相对两个值的乘积赋值,但很多人无意识中可能这么做,以及一个打字错误 if(a*b=c) //其实想做一个比较动作,即 ==
加上const 就可以省下这些恼人的错误
####################################################################################################
const成员函数
const指出函数能做的操作,也使操作“const”对象成为可能,如条款二十所言,改善C++程序效率的一个根本办法是以 pass-by-reference-to-const方式传递对象,而此技术可行的前提是,我们有const函数可用来处理取得的const对象。
(注:在C++中,只有被声明为const的成员函数才能被一个const类对象调用。)
如果两个成员函数只是常量性不同,则他们是可以被重载的。考虑以下class
如下调用
这其中当然不会有任何错误:你仅仅调用了const成员函数,取了其地址,但你还是改变了它的值。
关于const函数的重载,可以采用代码重用。
用non-const版本调用const版本,而不是反过来,否则,因为non-const可能对对象做出改动,而const承诺不改动对象,这样是危险的。
利用转型static_cast和const_cast
(注:const_cast用来将类型的const、volatile和__unaligned属性移除。static_cast则不具这样的功能)
关于指针的const,如果const出现在*左边,表示被指物是常量,如果出现在*右边,则表示指针是常量,如果两边都有,则表示指针和被指物都是常量。
void f1(const int* a); //f1获得一个指针,指向一个常量
void f2(int const * a); //f2也是
void f3(int* const a); //f3获得一个常量指针,即指针不可指向别处
STL的迭代器就是以指针为根据塑造出来的,声明迭代器为const就像声明指针为const一样,即,你可以修改迭代器指向的东西的值,但这个迭代器不可以指向不同
的东西。如果你希望迭代器所指的东西不可改动,则需要 const_iterator:
std::vector<int> vec;
const std::vector<int>::iterator iter = vec.begin(); //iter的作用像个 T* const
*iter = 10; //没问题,改变iter所指物的值
++iter; //错误! iter是const
std::vector<int>::const_iterator citer = vec.begin(); //citer的作用像个const T*
*citer =10; //错误!*citer是const
++citer; //没问题,改变citer
为函数返回值加上const
class Rational {};
const Rational operator*(const Rational& lhs,const Rational& rhs);
用以阻止这样的暴行
Rational a,b,c;
(a*b)=c;
尽管难以想象为什么会有人相对两个值的乘积赋值,但很多人无意识中可能这么做,以及一个打字错误 if(a*b=c) //其实想做一个比较动作,即 ==
加上const 就可以省下这些恼人的错误
####################################################################################################
const成员函数
const指出函数能做的操作,也使操作“const”对象成为可能,如条款二十所言,改善C++程序效率的一个根本办法是以 pass-by-reference-to-const方式传递对象,而此技术可行的前提是,我们有const函数可用来处理取得的const对象。
(注:在C++中,只有被声明为const的成员函数才能被一个const类对象调用。)
如果两个成员函数只是常量性不同,则他们是可以被重载的。考虑以下class
class TextBlock{
public:
const char& operator[](std::size_t position) const //operator[] for const
{return text[position];}
char& operator[](std::size_t position) //operator[] for non-const
{return text[position];}
private:
std::string text;
}
TextBlock的operator[]s可以被这么使用:
TextBlock tb("Hello");
std::cout << tb[0]; //调用non-const operator[]
const TextBlock ctb("World");
std::cout << ctb[0]; //调用const operator[]
如下调用
tb[0]='x'; //没问题
ctb[0]='x'; //错误
上述错误起因于对一个“由const版的operator[]返回”的const char&实行赋值动作。
也注意,non-const版本返回的是char&,不是char,否则就是对返回的拷贝值进行赋值动作,显然不合法。
const成员函数不允许修改class对象的数据成员,除非在其数据成员声明前加上 mutable ,这样,及时在const成员函数中,这些数据成员也可以被修改。
对于const对象
const TexrtBlock cctb("Hello");
char *pc=&cctb[0];
*pc='J';
这其中当然不会有任何错误:你仅仅调用了const成员函数,取了其地址,但你还是改变了它的值。
关于const函数的重载,可以采用代码重用。
用non-const版本调用const版本,而不是反过来,否则,因为non-const可能对对象做出改动,而const承诺不改动对象,这样是危险的。
利用转型static_cast和const_cast
(注:const_cast用来将类型的const、volatile和__unaligned属性移除。static_cast则不具这样的功能)
class TextBlock{
public:
const char& operator[](std::size_t position) const //operator[] for const
{return text[position];}
char& operator[](std::size_t position) //operator[] for non-const
{
return
const_cast<char&>(
static_cast<const TextBlock&>(*this)
[position]
);
}
};