指针
const位置
char greeting[] = "Hello";
char *p = greeting;
const char *p = greeting;
char * const p = greeting;
const char * const p = greeting;
const在 *
号左边,代表指针指向的对象是const的。如果在右边,代表这个指针是const的。
相同const
void f1(const Widget *pw); // f1 takes a pointer to a constant Widget object
void f2(Widget const *pw); // so does f2
STL 迭代器const
std::vector<int> vec;
const std::vector<int>::iterator iter = vec.begin() ;//指针本身是const的
*iter = 10; // Right
++iter; // Error
std::vector<int>::const_iterator cIter = vec.begin( ); //指针指向的对象是const的
*cIter = 10; // Error
++cIter; // Right
函数与const
返回值const
class Rational { ... };
const Rational operator*(const Rational& lhs, const Rational& rhs);
返回值为const的原因
- if 错用
if (a * b = c) ...
- 书写错误
Rational a, b, c;
(a * b) = c;
参数const
同函数内部的local const一样。
const成员函数
- 得知那个函数可以改动对象内容
- 如果两个成员函数常量性不同,则他们可以重载。
class TextBlock {
public:
const char& operator[](std::size_t position) const
{
return text[position];
}
char& operator[](std::size_t position)
{
return text[position];
}
private:
std::string text;
};
TextBlock tb("Hello");
std::cout << tb[0]; // call non-const version
const TextBlock ctb("World");
std::cout << ctb[0]; // call const version
应用
void print(const TextBlock& ctb)
{
std::cout << ctb[0]; // calls const TextBlock::operator[]
}
std::cout << tb[0];
tb[0] = ’x’;
std::cout << ctb[0];
ctb[0] = ’x’; // Error
bitwise constness vs logic constness
c++默认支持bitwise constness
缺点
class CTextBlock {
public:
char& operator[](std::size_t position) const
{
return pText[position]; //虽然满足C++的bitwise constness,但是实际上外部是可以修改pText所指向的内容
}
private:
char *pText;
};
比如这样做
const CTextBlock cctb("Hello");
char *pc = &cctb[0];
*pc = ’J’;
logic constness
一个函数可以修改某些类里面的变量,但是被外部用户感知到。
class CTextBlock {
public:
std::size_t length() const;
private:
char *pText;
std::size_t textLength;
bool lengthIsValid;
};
std::size_t CTextBlock::length() const
{
if (!lengthIsValid) {
textLength = std::strlen(pText); //不满足C++的bitwise constness
lengthIsValid = true; //不满足C++的bitwise constness
}
return textLength;
}
怎么办?
class CTextBlock {
public:
std::size_t length() const;
private:
char *pText;
mutable std::size_t textLength; // mutable释放掉non-static对象的const属性
mutable bool lengthIsValid; // mutable释放掉non-static对象的const属性
};
std::size_t CTextBlock::length() const
{
if (!lengthIsValid) {
textLength = std::strlen(pText);
lengthIsValid = true;
}
return textLength;
}
如何代码复用
class TextBlock {
public:
const char& operator[] (std::size_t position) const
{
return text[position];
}
char& operator[] (std::size_t position)
{
return const_cast<char &>(static_cast<const TextBlock>(*this)[position]);
}
};