C++中的const

const告诉编译器它所约束的对象是不允许被修改的,它可以作用于任何作用域类的对象(包括类对象),函数参数和返回值,及成员函数本体,使用它可以在编译时及时发现错误。

1)const与指针

const可以修饰指针本身,也可以修饰指针所指的对象,或者限制指针与其所指对象都为const,如下:

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

注意,const限制指针所指物不可修改时,有以下两种方式:

const char* p = "hello";
char const * p = "hello";

也就是说,const既可以位于数据类型前也可以位于数据类型后,但必须位于星号前,它们组合在一起用来修饰指针所指的对象。可以这样理解,星号前面的用来修饰被指物,星号

后面的用来修饰指针。

2)const与STL迭代器

STL迭代器与指针类似(难道不是一样的吗?),用const修饰迭代器就像声明指针为const一样,表示该迭代器不能指向不同的东西,如果要限制迭代器所指的对象不可修改,则需

要使用const_iterator,具体如下:

std::vector<int> v;
...
const std::vector<int>::iterator<int> iter = v.begin(); // iter是不能更改的,类似T* const
*iter++; //ok!
iter++; //error, iter是const常量

std::vector<int>::const_iterator<int> iter = v.beign(); //iter不是const,所指对象是const,不能更改
*iter++; //error!
iter++; //ok!

3)const修饰函数参数及返回值

对于函数声明:

const int operator*(const int& a, const int& b)
{
  return a*b;
}

它表示函数的参数和返回值都是不可以被修改的,所以下面的代码就是错误的:

int a = 3;
int b = 4;
int c = 5;
a*b = c; //a*b返回的是一个const常量,不可以修改

4)const与成员函数

a. 被const修饰的成员函数使得操作“const对象”成为可能,例如下面的代码编译就无法通过:

1  class Head
 2  {
 3    public:
 4      Head(string s) { pText = s; }
 5      char& operator[](size_t pos)
 6      {
 7        return pText[pos];
 8      }        
 9      private:
10        string pText;
11  }    
12  
13  int main()
14  {
15      const Head h1("Hello");
16      cout<<h1[1]<<endl;     //成员函数operator[]不能操作const对象 
17  }

此时可以添加const成员函数来操作const对象:

const char& operator[](std::size_t pos) const { return pText[pos]; }

b. 被const修饰的成员函数不改动任何非static成员变量,下面的情况除外:成员变量是一个指针类型,此时指针所指的地址不可以改变,但指针所指的对象却可以改变。比如将

上面代码中的成员变量pText改为char*类型,即声明如下:

char* pText;

同时令对应的const成员函数的返回值不再是const类型,具体修改如下:

char& operator[](std::size_t pos) const { return pText[pos]; }

那么下面const成员函数调用也是正确的:

const Head h2("Good");
char* p = &h2[0];
*p = 'J'; //此时pText所指向的字符串为“Jood”

这样的情况编译器能够通过是因为在const成员函数确实没有改变成员变量pText的值,只是改变了该值对应的变量。如果执意要在const成员函数中对成员变量进行赋值操作,那

么可以引入摆动场:mutable,它将释放在const成员函数中非static成员变量的不可改动性。

例如如下代码将通过编译:

1 class Head
 2 {
 3   public:
 4     ...
 5     size_t length() const;
 6  
 7    private:
 8     char* pText;
 9     mutable size_t textLength;  //表示这些变量可能经常会被改动,即使在
10     mutable bool LengthIsValid; //const成员函数里也有可能被修改
11 };
12  
13 size_t Head::length()
14 {
15   if(!LengthIsValid)
16   {
17     textLength = strlen(pText);
18     LengthIsValid = true;
19   }
20 }

5)const转型

如果两个重载函数只是在是否是常量性上有区别,要做的事几乎一样,那么可以通过将常量性转除来实现调用两次却只执行一次的功能,这样一来就避免了代码的重复,从而减

少编译时间,代码维护时间以及避免代码膨胀等问题。因为const成员函数的本意是不修改对象,而non-const成员函数却可以对对象做任意的修改,所以在const成员函数中调用

non-const是不合理也是不允许的,但是在non-const成员函数中调用const成员函数却是可行的,具体如下:

1 class Head
 2 {
 3     public:
 4     ...
 5     const char& operator[](std::size_t pos) const
 6     {
 7         return pText[pos];
 8     }
 9     char& operator[](std::size_t pos)
10     {
11       return const_cast<char&>(static_cast<const Head&>(*this)[pos]);
12     }
13 }

上述代码中有两次转型操作,首先通过static_cast<constHead&>将类型为Head&的*this转为const Head&类型,从而调用const的成员函数,然后通过const_cast去掉const成员函数返回值的const属性。

切记:const成员函数不可以调用non-const成员函数。
原文链接: https://www.cnblogs.com/sophia-yun/archive/2013/05/03/3057280.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/86905

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月9日 下午10:51
下一篇 2023年2月9日 下午10:51

相关推荐