常量正确性:const char const * const GetName const(//内容);

6

因为这是我写的一道期中考试题,我不理解答案,所以被标记为作业。我被要求解释以下语句中每个const的目的:

const char const * const GetName() const { return m_name; };

那么,每个常量的解释是什么呢?

4
代码可能不同,因为你发布的内容是不正确的。它很可能是以下这行代码:class X { const char * const getName() const { return m_name; } ... - David Rodríguez - dribeas
等一下,你写了期中考试吗? - tster
2
在C99中,const char const中的双重const是有效的,但在C++中不是。只允许一个const,但删除哪个并不重要。 - Johannes Schaub - litb
抱歉,打错了。是const要放在函数前面。我几个月前写的期中考试。 - user189320
1
@tster:“写测试”是加拿大人(以及可能是英国人和其他几个国家的人)所说的“参加测试”。对于他们来说,这并不意味着“创建测试”,因此4501并没有说他们创建了这个测试并且不理解问题。 - David Stone
8个回答

6
从右边获取它们。在分号之前的那个表示这是一个设计级别常量,即不改变对象的状态。 (将其视为只读方法。)
好的,现在回到返回值:
const char const *const

这是一个指向常量的指针 ... 现在我们来看情况失控!你有一个额外的 const -- 这是一个语法错误。下列两种写法是等价的:const TT const。如果你去掉其中一个 const,你会得到一个指向常量字符的常量指针。这样说清楚了吗?


澄清一下,您例子中的 T 是 char,而不是 char*。因此,将其放在一起:const char *const 等同于 char const * const。 - Marcin
@4501:请在符合规范的编译器中尝试此操作。 - dirkgently
1
它指向常量字符和常量字符S。只有上下文才能使区别变得相关,因为您可以通过索引该指针来获取内存中的任何地址。 - Dan Olson
(a) 在非法的情况下,你可以通过对指针进行索引来获取内存中的任何地址。 (b) 在分段存储结构的体系架构中,实际上根本不行。 - Steve Jessop
(因此const int const one = 1;也可以) - configurator
显示剩余2条评论

2

您的代码中有一个超出语法限制的const,该代码无法编译。请将“char”和“*”之间的“const”删除。此外,最后一个const必须位于函数体之前。从右到左阅读这样的内容会更有帮助。

const char * const GetName() const { return m_name; };

你有一个const函数(即该函数不会改变类的状态),它返回一个指向const char的const指针。


@dribeas,那是一个函数。在C++中不存在方法。 - Johannes Schaub - litb
是的,你关于主体的说法是正确的,但是关于方法与函数声明的部分不正确。 - Ed S.
在期中考试题中,指针前面有一个const关键字。 - user189320
@4501:是的,它是错误的,所以我修复了它。请阅读整篇帖子。@Drakosha:好吧,我不需要,但是是的,我检查过了,不,它无法编译。如果它是有效的C语言,请解释一下额外的const会意味着什么。 - Ed S.
是的Johannes,我想说的是“有效的C ++”。 - Ed S.
显示剩余4条评论

2

(1) const char数组的内容是不可更改的。当您返回对象成员的指针时,这非常有用。由于您将指向成员的指针交给第三方,因此希望防止它从外部被更改。

(2) 这种形式不经常使用,本质上与(1)相同。

(3) 我们的char数组指针是const的,因此您无法更改指针指向的位置。

(4) 它限定了GetName()方法本身,意味着该方法不会更改应用它的类。因此,它只能为此类型的const对象调用。通常使用的形式是GetName(...) const。

正如在其他答案中已经提到的,"记住"它的诀窍是从右到左阅读:

  • const T * - 指向const T的指针
  • T * const - 指向T的const指针

1
错误:(1)和(2)是等价的。也就是说,const TT const是相同的。另一方面,T const *T * const是不同的,一个标记T为常量,另一个标记指针为常量。 - David Rodríguez - dribeas

1

编辑:看起来我在将代码粘贴到Comeau中时出现了错误,或者原始答案已被编辑为正确的代码。无论哪种情况,我都将保留以下答案,就好像代码不正确一样。

Comeau在线编译器给出了以下结果:

"ComeauTest.c",第4行:错误:类型限定符指定多次
const char const * const GetName() { return m_name; } const; ^

"ComeauTest.c",第4行:警告:返回类型上的类型限定符是无意义的const char const * const GetName() { return m_name; } const; ^

"ComeauTest.c",第4行:错误:声明未声明任何内容const char const * const GetName() { return m_name; } const;

这意味着您的语句格式不正确。

const char const * const GetName() { return m_name; } const;

第一个和第二个常量意思相同。您不能多次指定相同的限定符,因此必须删除其中一个才能使代码编译通过。这两个常量都指定了 GetName 返回的指针所指向的值不能被修改,因此像这样的代码是无效的:
const char* name = c.GetName();
name[0] = 'a';

第三个const指定GetName()返回的指针本身不能被修改,但正如Comeau所指出的那样,在返回值上这并没有实现任何东西,因为返回值是指针的副本而不是指针本身,并且可以分配给非const指针。

第四个const放错了位置,它应该在GetName和函数体之间,像这样:

const char* GetName() const { return m.name; }

这个 const 指定 GetName 在执行期间不会修改类的任何成员。假设 GetName 是类 Person 的一个成员,则以下代码是允许的:

const Person& p;
p.GetName();

如果没有这个 const,上面的代码将会失败。


指出使返回的指针不可修改是毫无意义的,这一点值得赞赏。GCC也对此发出了警告(如果您将警告视为错误,则代码仍无法编译 :))。了解这些常量的含义很重要,但函数的返回类型似乎是一个相当不幸的选择来进行演示。 - UncleBens

1

你可能在第二个const关键字前漏掉了“*”符号。

const char * const * const GetName() const { return m_name; };

这意味着该函数返回指向常量字符的常量指针的常量指针。


0

最后一个 const:

  • 函数不会改变类的私有成员

最后一个 const 后面:

  • 它是一个常量指针(即指向的位置是恒定的)

第二个 const:

  • 该函数返回一个 const char(即字符的内容是恒定的)

第一个:

  • 不知道?

所以完整的意思是:该函数返回一个常量指针(始终指向同一位置),指向一个常量 char(始终具有相同的内容),并且该函数不修改类的状态。


一个const方法不能改变类的任何成员,也不能调用任何非const方法。 - quamrana
@quamrana:一个const方法可以改变静态或可变的数据成员。 - Jerry Coffin
@Jerry:你说得没错。让我重新表述一下:const方法不能修改任何公有的、受保护的或私有的成员,除非它们是静态的或可变的。 - quamrana

0

const (1) char const(2) * const GetName() { return m_name; } const(3);

const char * const result = aaa.GetNAme();

3 - const 方法,不允许更改成员或调用任何非const方法。

1 - 不允许在指针内部进行修改,即 *result = ..

2 - 不允许移动指针,即 result = NULL


0

给定:

const char const * const GetName() const { return m_name; };

第一个和第二个const是等价的,但只允许其中一个--即你可以在类型(在这种情况下为char)之前或之后放置const,但只能选择其中一个,而不能两者都有。无论哪种方式,都表示指针所指向的字符不能被写入。

在'*'后面的const意味着函数返回的指针本身不能被修改。这在返回类型中很少见--你返回的是一个值,在任何情况下都不能被修改(通常只是分配给某个变量)。然而,在其他情况下,这可能是有意义的。

第三个const只允许在一个成员函数中使用。它表示当调用此函数时,接收到的this指针将是T const * const而不是T * const,因此成员函数只能修改对象的staticmutable成员,并且如果调用其他成员函数,它们也必须是const。然而,有一个警告,它也可以去除const属性,这样它就可以修改所需的内容(但需要注意的是,如果对象最初被定义为const,而不仅仅是具有指向普通(非const)对象的const指针,则结果将是未定义的)。

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