effective c++(03)之const使用方法

char greeting[] = "hello";
char* p = greeting;                       //non-const pointer,non-const data
const char* p = greeting;              //non-const pointer, const data
char* const p = greeting;              //const pointer,non-const data
const char* const p = greeting;     //const pointer, const data

以上为const面对指针时所产生的四种情况。

 

 const 如出现在星号左边,表示被指物是常量;如果出现在星号右边,表示指针本身是常量;如果出现在星号两边,表示被指物和指针都是常量。

如果被指物是常量,const写在类型之前和类型之后都可以,意义相同,一下两种写法相同:

void f1( const type* pw );
void f2( type const* pw );

 

而对于STL迭代器。所有的迭代器作用就跟T*一样。声明迭代器为const就像声明一个const指针一样,表明迭代器不能指向不同的东西。如果想让迭代器指向的东西不可改变,则需要声明const_iterator。如下:

const vector<int>::iterator iter = vec.begin();     //如 T* const
*iter = 10;                                                        //没有问题
iter++;                                                             //不可执行

vector<int>::const_iterator citer = vec.begin();   //如 const T*
*citer = 10;                                                       //不可执行
citer++;                                                            //可以


 

const最具有威力的用法是面对函数声明时的应用:

class Rational {...};
const Rational operator* ( const Rational& lhs, const Rational& rhs);

Rational a,b,c;
...
(a*b)=c;

如以上例子,对两个数值的乘积做了一次赋值,将operator*的回传声明为const可以预防这种没有意思的动作。

const成员函数

如果函数的返回类型是内置类型,那么如果改动函数返回值从来就不合法。如果返回类型为引用,则可以给返回值赋值。

class TextBlock{
public:
    const char& operator[]( size_t position ) const
    {
        return text[position];
    }
    char& operator[](size_t position)
    {
        return text[position];
    }
private:
    string text;
};

如上类中,如果有以下调用:

TextBlock tb("hello");
cout << tb[0];
const TextBlock ctb("world");
cout << ctb[0];

tb直接调用类中的non-const成员函数,ctb调用的是const成员函数,如下代码:

cout << tb[0];
tb[0] = 'x';
cout << ctb[0];
ctb[0] = 'x';

ctb[0]='x'是不可以被执行的,因为const成员函数返回的是const的引用,并且const成员函数所使用的数据成员不可以被更改。

但是由于以上的方法却产生了以下问题:

class CTextBlock{
public:
    char& operator[]( size_t position ) const
    {
        return pText[position];
    }
private:
    char* pText;
};

对于以上的类在如下调用时:

const CTextBlock cctb("hello");
char* pc = &cctb[0];
*pc = 'J';

此时cctb为‘Jello’。
以上为 bitwise const 的观点,虽然const成员对象没有改变类的数据成员,但是整体上是改变了,这样的情况下const类成员意义不大,终究还是改变了其值。

于是产生了logical constness的观点:

class CTextBlock{
public:
    size_t length() const;
private:
    char* pText;
    size_t textLength;
    bool lengthIsValid;
};
size_t CTextBlock::length() const
{
    textLength = strlen(pText);
    lengthIsValid = true;
    return textLength;
}

以上代码显然没法执行,因为在length为const成员函数不能改变数据成员。logical constness的观点如下:

class CTextBlock{
public:
    size_t length() const;
private:
    char* pText;
    mutable size_t textLength;
    mutable bool lengthIsValid;
};
size_t CTextBlock::length() const
{
    textLength = strlen(pText);
    lengthIsValid = true;
    return textLength;
}

在const成员函数前加上mutable即可实现const成员函数改变数据成员。

posted @ 2013-07-09 17:40  2011winseu  阅读(227)  评论(0编辑  收藏  举报