C++ Exceptional 有关const的用法

下面通过一个例子来解释const在C++中的用法:

class Polygon
{
public:
    Polygon() : area_(-1) {}
    void AddPoint(const Point pt) { InvalidateArea();
                                    points_.push_back(pt);
                                   }
    Point GetPoint(const int i) { return points_[i]; }
    int GetNumPoints()          {return points_.size(); }
    double GetArea()
    {
        if(area_ < 0)  //if not yet calculated and cached
        {
            CalcArea();   //calculate now
        }
        return area_;
    }                
private:
    void InvalidateArea() { area_ = -1; }
    void CalcArea()
    {
        area_ = 0;
        vector<Point>::iterator i;
        for( i = points_.begin(); i != points_.end(); ++i)
            area_ += /* some work */
    }                  
    vector<Points> points_;
    double area_;
};

Polygon operator+(Polygon& lhs, Pplygon& rhs)
{
    Polygon ret = lhs;
    int last = rhs.GetNumPoints();
    for(int i = 0; i < last; ++i) // concatenate
    {
        ret.AddPoint(rhs.GetPoint(i));
    }
    return ret;
}

void f(const Polygon& poly)
{
    const_cast<Polygon&>(poly).AddPoint(Point(0, 0));
}

void g(Polygon& const rPoly) { rPoly.AddPoint(Point(1, 1)); }

void h(Polygon* const pPoly) { pPoly->AddPoint(Point(2, 2));}

int main()
{
    Polygon poly;
    const Polygon cpoly;
    f(poly);
    f(cpoly);
    g(poly);
    h(&poly);
}

请找出以上代码中有关const的用法的问题:
1. void AddPoint(const Point pt) 中按照值的方式传参的时候,制定const 修饰符是没有意义的。因为按照值的方式传参时,其实编译器会生成一个临时变量,而把这个临时变量声明为const 的,是没有任何意义的。所以记住一点,按照值的方式传参时,没必要用const 来修饰。另外这里用const引用的方式传参更高效一些,所以应该改成void AddPoint(const Point& pt)
2. Point GetPoint(const int i) 这个函数声明存在三个问题,第一个这个函数应该声明为const 的,第二个,当按照值的方式传递参数时没必要把这个参数声明为const 的,原因上面已经讲了。第三个,当按照值的方式返回时,如果不是built-in类型的变量,要把返回的值声明为const的,以避免外部的调用者对这个临时变量做改变。所以最终应该声明为如下形式:const Point GetPoint(int i) const
3. int GetNumPoints() 这个函数应该声明为const 的,另外由于返回的是一个built-in类型的值,所以没必要把返回值声明为const 的。所以应该声明为:int GetNumPoints() const
4. double GetArea() 这个函数应该声明为const 的,这里你也许会问,这个函数会改变类内部的成员变量,怎么能声明为const 的呢。这里我要说的是,虽然这个函数会改变类内部的成员变量,但它并不会改变类的观察状态,这里只是为了高效,对area_ 做了缓存。为了能在const函数中改变area_ 的值,这里我们需要将area_ 声明为mutable 的。
5. void CalcArea() 这个函数很明显的应该声明为const 的,以为它并不会改变类的任何状态。
6. vector<Point>::iterator i 这里的iterator 并不会改变目标的值,所以应该用const_iterator
7. Polygon operator+(Polygon& lhs, Polygon& rhs) 这里的参数应该声明为const 类型的
8. void f(const Polygon& poly) 在这个函数里,试图把一个const的引用类型用const_cast 去掉const 属性,这在C++里会产生一种未定义的后果,所以不要这么做,传参的时候直接传递Polygon& 类型的就可以了,没必要加const
9. void g(Polygon& const rPoly) 这里的const 是没有必要的,因为引用传参的时候rPoly 就已经是const 的了
10. void h(Polygon* const pPoly) 这里的const 同样也是没必要的,因为这里的指针pPoly是按值传递的,把它声明为const 是没必要的。

总而言之,言而总之,在能用const 的地方尽量用const,并合理的配合mutable 来设计类。当然也不能乱用,在按值传参的时候,把值声明为const 是没有意义的。在按值返回时,尽量把返回值声明为const 的,因为这可以避免对编译器生成的临时变量做改变。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值