在返回类型中,“const”是什么意思?在函数参数中又是什么意思?成员函数后面的“const”又代表什么?

111
const int* const Method3(const int* const&) const;

有人可以解释一下每个const的用法吗?


30
我很喜欢这种解读复杂声明的方法:http://c-faq.com/decl/spiral.anderson.html。 - Jason
12个回答

113

如果你将其改写为完全等效的形式,那么理解起来会更容易。

// 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表明左侧的intconst(不能更改为不同的值)。

#2表明左侧的指针是const

#1表明左侧的intconst

将所有内容组合起来,可以将其解释为一个名为Method3const成员函数,它接受对int const(或const int)指针的const引用,并返回对int constconst int)指针的const引用。

(注意:#2 完全是多余的。)


82

阅读此链接:https://isocpp.org/wiki/faq/const-correctness

最后的const表示函数Method3不会修改其类中的非可变成员。

const int * const表示指向常量整数的常量指针:即一个指针不能改变,指向一个不能改变的整数:唯一的区别在于它可以是null

const int * const &表示对常量整数的常量指针的引用。通常不会传递指针的引用;const int * &更有意义,因为这意味着在方法调用期间可以更改指针,这是我能想到唯一需要通过引用传递指针的原因,const int * const &const int * const基本相同,只不过它可能不如效率高,因为指针是平凡数据类型(POD),通常应通过值传递它们。


“const int* const” 表示一个指向常量整数的常量指针,即一个不能被更改的指针,指向一个不能被更改的整数。稍作修正,“const int*” 指向的内容仍然可以更改,只是不能通过该指针进行更改。例如,int x = 1; const int *p = &x; x = 2; 是成功的,但是 *p = 2; 会失败。 - scatter

23

首先,const T 等价于 T const

因此,const int* const 等同于 int const * const

在阅读带有很多 const 符号和指针的表达式时,请尝试从右到左阅读(应用上述转换后)。因此,在本例中,返回值是一个指向常量 int 的常量指针。在这里使指针本身成为const没有意义,因为返回值不是可以修改的左值。然而,使指向对象成为const可以确保调用者无法修改 Method3 返回的 int(或int数组)。

const int*const& 变成了 int const*const&,因此它是一个指向常量 int 的常量指针的引用。通过引用传递常量指针也没有意义——由于指针是 const 的,因此无法修改引用的值,并且引用和指针占用相等的存储空间,因此没有任何节省空间的好处。

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


2
投票支持这个回答(以及ildjarn的相似回答),部分原因是因为它强调如果不把第一个“const”放在短语的开头,整个代码更有意义。这正是我认为在那里使用“const”是不好的实践,尽管语言允许,而且这是最常见的用法。 - T.E.D.

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的常量指针。
希望这有所帮助,
Jason

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*
希望这可以帮到你。


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

1

从右到左阅读可以更容易地理解修饰符。

一个const方法,它接受一个指向const int的const指针的引用,名为Method3,返回一个指向const int的const指针。

  1. const方法不能修改成员(除非它们明确地被声明为mutable
  2. const指针不能被改变以指向其他内容
  3. const int(或任何其他类型)不能被修改

1

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

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

const #3: 传递给函数的指针类型指向一个const int。

const #4: 传递给函数的指针值本身是一个const指针。声明一个传递给函数的值为const通常是没有意义的,但是由于这个值是通过引用传递的,所以它可以有意义。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接