C ++常量用法说明


Answers:


77

阅读此内容:https : //isocpp.org/wiki/faq/const-correctness

最终const意味着功能Method3不会修改其类的非可变成员。

const int* const表示指向常量int的常量指针:即,不能更改的指针,指向不能更改的int指针:和之间的唯一区别在于const int&它可以是null

const int* const&表示对指向常量int的常量指针的引用。通常,指针不通过引用传递。const int* &更有意义,因为这意味着可以在方法调用期间更改指针,这是我看到的通过引用传递指针的唯一原因,const int* const&其所有意图和目的const int* const都与之相同,只是它的效率可能较低由于指针是普通的旧数据(POD)类型,因此通常应按值传递这些类型。


103

如果将其重写为完全等效的内容,则更容易理解

// v───v───v───v───v───v───v───v───v───v───v───v─┬┐
//                                               ││
//  v──#1    v─#2             v──#3    v─#4      #5
   int const * const Method3(int const * const&) const;

然后从右到左阅读。

#5表示左侧的整个函数声明为const,这表示这一定是成员函数,而不是自由函数。

#4表示左边的指针是const(不能更改为指向其他地址)。

#3表示int左侧的是const(不得更改为其他值)。

#2表示左侧的指针是const

#1表示int的左侧是const

将它们放在一起,您可以将其读为一个const名为的成员函数,该成员函数Method3引用指向的const指针int constconst int如果需要,可以引用,然后返回const指向的指针int constconst int))。

(Nb#2 完全多余。)


22

首先const T等于T const

const int* const因此等于int const * const

读取其中包含许多const标记和指针的表达式时,请始终尝试从右到左读取它们(应用上面的转换之后)。因此,在这种情况下,返回值是指向constintconst指针。在const这里,使指针本身没有意义,因为返回值不是可以修改的左值。const但是,指定为pointee 可以确保调用者不能修改由其返回的int(或的数组intMethod3

const int*const&成为int const*const&,因此它是对指向const的const指针int引用。通过引用传递const指针也没有任何意义-您不能修改引用的值,因为指针为,const并且引用和指针占用相等的存储空间,因此也没有任何空间节省。

最后一个const表示该方法未修改该this对象。this方法主体中的指针将具有(理论上的)声明T const * const this。这意味着一个const T*对象将能够调用T::Method3()


2
投票(和ildjarn类似的答案),部分原因是要指出,如果您不将第一个consts放在短语的开头,那么整个事情就更有意义了。这就是为什么我认为const即使在语言允许的情况下也放在那里是不好的做法,这是最常见的用法。
TED

12

记住规则的一种简单方法const是这样思考:const适用于事物的左侧,除非其左侧没有任何东西。

因此,在的情况下const int * const,第一个const的左侧不包含任何内容,因此适用于它,int而第二个const的左侧则包含一些内容,因此适用于指针。

该规则还告诉您在您拥有的情况下会发生什么const int const *。由于两个const都适用int于此表达式,因此是多余的,因此无效。


3
const /* don't modify the int or array of ints' value(s) */
int* const /* as a retval, ignored. useless declaration */
Method3(const /* don't modify the int or array of ints' value(s) */
int* const /* don't modify the pointer's value, the address to which `pointer` points to. e.g. you cannot say `++pointer` */
&) const; /* this method does not modify the instance/object which implements the method */

3

我喜欢使用“时钟”或“螺旋”方法,其中从标识符名称(在这种情况下Method3)开始,您从左到右从左到右依次读取等等,以便进行解码命名约定。这样const int* const Method3(const int* const&) const的类方法也不会更改(任何未命名类的)任何类成员,并且对指向常量的指针进行常量引用,int并返回指向常量的常量指针int

希望这可以帮助,

杰森


2

在C ++中记住const的一种简单方法是,当您看到如下形式的代码时:

XXX const;
const YYY;

XXX,YYY将为常数,
XXX const形式为:

function ( def var ) const;    ------#1
* const;                       ------#2

const YYY 形成:

const int;                     ------#3
const double;

人们通常使用这些类型。当您看到"const&"某个地方时,不要感到困惑,const在描述自己之前的东西。所以现在这个问题的答案不言而喻。

const int* const Method3(const int* const&) const;
  |          |             |          |       |
  #3         #2            #3         #2      #1

2

我只想提一提,const int* const&确实是对的不断引用const int*。例如:

int i = 0;
int j = 1;
int* p = &i;
int* q = &j;
const int* const& cpref = p;
cpref = q; //Error: assignment of read-only reference 'cpref'

的情况也是如此int* const&,其含义是:“对”的常量引用int*
但是const int*&是的非恒定引用const int*
希望这可以帮助。


1

从右到左阅读使理解修饰语更加容易。

const方法,该方法引用指向const int Method3的const指针,该const返回指向const int的const指针。

  1. const方法不能修改成员(除非它们是显式的 mutable
  2. const指针不能更改为指向其他内容
  3. const int(或任何其他类型)不能被修改

1

const#1:Method3返回的指针指向const int。

const#2:函数本身返回的指针值为const。这是一个无用的const(尽管在语法上是有效的),因为函数的返回值不能为l值。

const#3:通过引用传递给函数的指针类型指向const int。

const#4:通过引用传递给函数的指针值本身就是const指针。将值声明为const传递给函数通常是没有意义的,但是此值是通过引用传递的,因此它可能是有意义的。

const#5:函数(可能是成员函数)是const,这意味着它不允许(a)向对象所属的对象的任何成员分配新值,或者(b)调用非const成员函数在对象或其任何成员上。


0
  • const 方法的最后是限定符,表示对象的状态不会更改。

  • const int*const&表示通过引用接收指向const位置的const指针。它既不能更改为指向其他位置,也不能更改其指向的值。

  • const int*const 是返回值,它也是指向恒定位置的恒定指针。


0

一些例子可能很好地证明了这个概念,恕我直言越好。

class TestClass
{
private:
   int iValue;
   int* oValuePtr;
   int& oValueRef;

public:
   int TestClass::ByValMethod1(int Value)
   {
      // Value can be modified
      Value++;

      // iValue can be modified
      iValue = Value;
      iValue += 1;

      // Return value can be modified
      return ++iValue;
   }

   int TestClass::ByValMethod2(const int Value)
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // iValue can be modified
      iValue = Value;
      iValue += 1;

      // Return value can be modified
      return ++iValue;
   }

   const int TestClass::ByValMethod3(int Value)
   {
      // Value can be modified
      Value++;

      // iValue can be modified
      iValue = Value;
      iValue += 1;

      // Return value can be modified
      return ++iValue;
   }

   const int TestClass::ByValMethod4(const int Value)
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // iValue can be modified
      iValue = Value;
      iValue += 1;

      // Return value can be modified
      return ++iValue;
   }

   const int TestClass::ByValMethod5(const int Value) const
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // iValue *cannot* be modified
      // Access through a const object
      iValue = Value;
      iValue += 1;

      // Return value *cannot* be modified
      // Access through a const object
      return ++iValue;
   }

   int& TestClass::ByRefMethod1(int& Value)
   {
      // Value can be modified
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   int& TestClass::ByRefMethod2(const int& Value)
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   const int& TestClass::ByRefMethod3(int& Value)
   {
      // Value can be modified
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   const int& TestClass::ByRefMethod4(const int& Value)
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   const int& TestClass::ByRefMethod5(const int& Value) const
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   int* TestClass::PointerMethod1(int* Value)
   {
      // Value can be modified
      Value++;

      // oValuePtr can be assigned
      oValuePtr = Value;

      // oValuePtr can be modified
      oValuePtr += 1;

      // Return value can be modified
      return ++oValuePtr;
   }

   int* TestClass::PointerMethod2(const int* Value)
   {
      // Value can be modified
      Value++;

      // oValuePtr cannot be assigned
      // const int* to int*
      oValuePtr = Value;

      // oValuePtr can be modified
      oValuePtr += 1;

      // Return value can be modified
      return ++oValuePtr;
   }

   const int* TestClass::PointerMethod3(int* Value)
   {
      // Value can be modified
      Value++;

      // oValuePtr can be assigned
      oValuePtr = Value;

      // iValue can be modified
      oValuePtr += 1;

      // Return value can be modified
      return ++oValuePtr;
   }

   const int* TestClass::PointerMethod4(const int* Value)
   {
      // Value cannot be modified
      Value++;

      // oValuePtr *cannot* be assigned
      // const int* to int*
      oValuePtr = Value;

      // oValuePtr can be modified
      oValuePtr += 1;

      // Return value can be modified
      return ++oValuePtr;
   }

   const int* TestClass::PointerMethod5(const int* Value) const
   {
      // Value can be modified
      ++Value;

      // oValuePtr *cannot* be assigned
      // const int* to int* const
      // Access through a const object
      oValuePtr = Value;

      // oValuePtr *cannot* be modified
      // Access through a const object
      oValuePtr += 1;

      // Return value *cannot* be modified
      return ++oValuePtr;
   }
};

我希望这有帮助!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.