美文网首页
条款03: 尽可能使用const

条款03: 尽可能使用const

作者: 未来已来_1cab | 来源:发表于2019-01-25 16:50 被阅读0次

标准C范畴下的尽可能使用const

面对指针,你可以指出指针自身、指针所指物,或两者都(或都不)是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

如果被指物是常量,可以写做:

void f1(const Widget* pw);

令函数返回一个常量值,往往可以降低客户错误而造成的意外,而又不至于放弃安全性和高效性。举个例子,考虑有理数的operator*声明式:

//写法一:类外写法
const Rational operator* (const Rational& lhs, const Rational& rhs);

许多程序员第一次看到这个声明时不免斜着眼睛说,唔,为什么返回一个const对象?原因是如果不这样客户就能实现这样的暴行:

Rational a, b, c;
...
if(a * b = c)    //喔欧,其实是想做一个比较动作!
{...}

将operator*的回传值声明为const可以预防那个“没意思的赋值动作”,这就是该那么做的原因。

STL范畴下的尽可能使用const

STL迭代器系以指针为根据塑模出来,所以迭代器的作用就像个T*指针。声明迭代器为const就像声明指针为const一样(即声明一个T* const指针),表示这个迭代器不得指向不同的东西,但它所指的值是可以改动的。如果你希望迭代器所指的东西不可被改动(即希望STL模拟一个const T*指针),你需要的是const_iterator:

#include <iostream>
#include <vector>
using namespace std;

int main()
{
        vector<int> vec(10, 1);
        // iter acts like a T* const
        const vector<int>::iterator iter = vec.begin();
        // OK, changes what iter points to
        *iter = 10; 
        //++iter; // error! iter is const
        //cIter acts like a const T*
        vector<int>::const_iterator cIter = vec.begin();
        //*cIter = 10; // error! *cIter is const
        ++cIter; // fine, changes cIter

        return 0;
}

Object Oriented C++范畴的尽可能使用const

将const实施于成员函数的目的,是为了确认该成员函数可作用于const对象身上。

#include <iostream>
#include <string>
using namespace std;

class TextBlock
{
public:
    TextBlock() : text("")
    {
    }
    TextBlock(const char t[]) : text(t)
    {
    }
    TextBlock(const TextBlock& tb) : text(tb.text)
    {
    }
    ~TextBlock(){}
    //写法二:类内写法
    const char& operator[](size_t position)const
    {
        return text[position];
    }
    char& operator[](size_t position)
    {
        cout << text << endl;
        text = "ByeBye";
        return text[position];
    }
private:
    string text;
};

int main(int argc, char* argv[])
{
    TextBlock tb("Hello");
    cout << tb[0] << endl;     //call non-const TextBlock::operator[]
    tb[0] = 'x';
    cout << tb[0] << endl;
    const TextBlock ctb("World");
    cout << ctb[0] << endl;   //call const TextBlock::operator[]
    /* 下面错误只因operator[]的返回类型以致,至于operator[]调用动作自身没问
     * 题。错误起因于企图对一个“由const版之operator[]返回”的const char&施行赋
     * 值动作。
     */
//  ctb[0] = 'x';

    return 0;
}

成员函数怎么才是真正的const的呢?

bitwise const阵营的人相信,成员函数只有在不更改对象之任何成员变量(static除外)时可以说是const。不幸的是许多成员函数虽然不十足具备const性质却能通过bitwise测试。

#include<iostream>
#include<string>
using namespace std;

class CTextBlock {
public:
    CTextBlock(const char t[]) : text(t)
    {
        pText = &text[0];
    }
    //inappropriate (but bitwise const) declaration of operator[]
    char& operator[](size_t position)const
    {
        return pText[position];
    }
    int putstring()const
    {
        cout << text << endl;
        return 0;
    }
private:
    string text;
    char *pText;
};

int main()
{
    const CTextBlock cctb("Hello"); // declare constant object
    //call the const operator[] to get a pointer to cctb's data
    char *pc = &cctb[0];
    cout << *pc << endl;
    *pc = 'J'; // cctb now has the value "Jello"
    cout << cctb[0] << endl;
    cctb.putstring();
    return 0;
}

logical constness一派主张,一个const成员函数可以修改它所处理的对象内的某些bits(下面例子即是此主张的技术上的处理技巧),但只有在客户端侦测不出的情况下才得如此,比如下面的例子,一个TextBlock的长度在逻辑上就应该是一个常量,所以求长度的函数设计为const函数。

#include <iostream>
#include <cstring>
using namespace std;

class CTextBlock {
public:
    size_t length() const;
private:
    char *pText;
    //these data members may
    mutable size_t textLength;
    //always be modified, even in const member functions
    mutable bool lengthIsValid;
};
size_t CTextBlock::length() const
{
    if (!lengthIsValid) {
        textLength = strlen(pText); // now fine
        lengthIsValid = true; // also fine
    }
    return textLength;
}

int main()
{
    return 0;
}

对于“bitwise-constness非我所欲”的问题,mutable是个解决办法,但它不能解决所有的const相关难题。比如:

在const和non-const成员函数中通过互相调用避免重复

#include<iostream>
#include<string>
using namespace std;

class TextBlock {
public:
    TextBlock(const char t[]) :text(t)
    {};
    const char& operator[](size_t position) const // same as before
    {
        return text[position];
    }
    char& operator[](size_t position) // now just calls const op[]
    {
        return
            /* cast away const on op[]'s return type; call const version of op[]
             */
            const_cast<char&>(
            /* We cast *this from its native type of TextBlock& to const TextBlock&.
             * In order to call const op[]
             */
                    static_cast<const TextBlock&>(*this)[position]);
    }
private:
    string text;
};

int main()
{
    TextBlock ctb("Hello");
    cout << ctb[0] << endl;

    return 0;
}

相关文章

网友评论

      本文标题:条款03: 尽可能使用const

      本文链接:https://www.haomeiwen.com/subject/vvcvjqtx.html