Const之前还是const之后?

AJG*_*G85 132 c c++ syntax const

首先,你可能知道const可以用来制作一个对象的数据或一个不可修改的指针或两者兼而有之.

const Object* obj; // can't change data
Object* const obj; // can't change pointer
const Object* const obj; // can't change data or pointer
Run Code Online (Sandbox Code Playgroud)

但是您也可以使用以下语法:

Object const *obj; // same as const Object* obj;
Run Code Online (Sandbox Code Playgroud)

唯一重要的是你把const关键字放在星号的哪一边.我个人更喜欢把const上式的左边指定它的数据是不可修改的,因为我觉得它读取我的左到右的心态更好,但其语法是先?

更重要的是,为什么有两种正确的const数据指定方式,如果有的话,你会更喜欢或需要哪种方式?

编辑:

所以听起来这是一个武断的决定,因为编译器应该如何解释事物的标准早在我出生之前起草了.因为const应用于关键字左侧的内容(默认情况下?)我猜他们认为添加"快捷方式"以应用关键字并以其他方式输入限定符至少直到声明更改为止时没有任何损害解析*或&...

这是C的情况,然后我假设?

Hea*_*utt 85

为什么有两种正确的const数据指定方式,如果有的话,您希望在哪种情况下或者需要哪种方式?

从本质上讲,在const星号之前的说明符中的位置无关紧要的原因是C语法是由Kernighan和Ritchie定义的.

他们以这种方式定义语法的原因很可能是他们的C编译器从左到右解析输入并在消耗它时完成处理每个令牌.使用*令牌会将当前声明的状态更改为指针类型.遇到const*意味着const限定符被施加到一个指针声明; 在此之前遇到它*意味着限定符应用于指向的数据.

因为const限定符出现在类型说明符之前或之后,语义含义不会改变,所以它可以被接受.

在声明函数指针时会出现类似的情况,其中:

  • void * function1(void)声明一个返回的函数void *,

  • void (* function2)(void)声明一个返回函数的函数指针void.

需要注意的是,语言语法支持从左到右的解析器.

  • Kernighan合着了这本书,但没有参与C的设计,只有Ritchie. (7认同)
  • 我永远不记得哪一个是哪个.多亏了你的解释,我终于有了mnemotechnic来记住它.谢谢!在`*`之前,编译器解析器不知道它是指针,因此它对于数据值是const.之后*它与常量指针有关.辉煌.最后它解释了为什么我可以做`const char`以及`char const`. (6认同)
  • 关于为什么这样做的猜测对我来说似乎很弱/自相矛盾。也就是说,如果我正在定义一种语言并编写一个编译器,并且我想保持简单并且“从左到右解析输入并在使用它时完成处理每个标记”,正如您所说,在我看来我会要求 `const` 总是出现在它符合条件的东西之后......正是这样,我总是可以在使用它后立即完成对 const 的处理。所以这似乎是*禁止* west-const 的论据,而不是允许它。 (3认同)
  • “因为如果const限定符出现在类型说明符之前或之后,语义不会改变,所以无论哪种方式都可以接受它。” 那不是循环推理吗?问题是*为何如此定义语义,所以我认为这句话没有任何作用。 (3认同)

hor*_*rst 67

规则是:

const适用于它剩下的东西.如果左边没有任何内容,则它适用于它的权利.

我更喜欢在const的右边使用const只是因为它是定义const的"原始"方式.

但我认为这是一个非常主观的观点.

  • 我更喜欢把它放在左边,但我觉得把它放在右边更有意义.您通常从右到左读取C++中的类型,例如`Object const*`是指向const Object的指针.如果你把`const`放在左边,它会读作指向const的指针,它实际上并不是很好. (15认同)
  • @HeathHunnicutt规则存在,但它有点复杂:http://c-faq.com/decl/spiral.anderson.html (3认同)
  • @HeathHunnicutt:螺旋规则是第一个评论者评论的扩展版本“您通常从右到左阅读 [C/]C++ 中的类型”。我猜你是在反驳这个。但是,我认为您可能指的是答案本身。 (3认同)
  • @Heath 我相信这更像是一个指南而不是规则,我经常听到它作为一种记住编译器将如何解释它的方式......我了解它是如何工作的,所以我只是对背后的思考过程感到好奇决定以两种方式支持它。 (2认同)

Mat*_*vis 49

我更喜欢第二种语法.它通过从右到左阅读类型声明帮助我跟踪'什么'是不变的:

Object * const obj;        // read right-to-left:  const pointer to Object
Object const * obj;        // read right-to-left:  pointer to const Object
Object const * const obj;  // read right-to-left:  const pointer to const Object
Run Code Online (Sandbox Code Playgroud)

  • 究竟。“指向常量对象的常量指针”是“对象const * const”,而不是“常量const Object *”。“ const”不能在左边,除非在特殊情况下如此之多的人绝对喜欢它。(请参阅上面的希思。) (3认同)

Bo *_*son 35

声明中关键字的顺序并非全部修复."一个真正的秩序"有很多替代品.像这样

int long const long unsigned volatile i = 0;
Run Code Online (Sandbox Code Playgroud)

或应该是

volatile unsigned long long int const i = 0;
Run Code Online (Sandbox Code Playgroud)

??

  • +1表示简单变量的完全混乱的定义.:) (18认同)
  • 这些都合法吗? (2认同)
  • @rubenvb - 是的,`unsigned`是一个类型,与`unsigned int`和`int unsigned`相同.`unsigned long`是另一种类型,与`unsigned long int`和`int long unsigned`相同.看模式? (2认同)
  • @Bo:我看到了混乱,必须有三个才能看到模式`;)`。好,谢谢 (2认同)

Jam*_*nze 7

第一条规则是使用本地编码标准所需的任何格式.在那之后:const当涉及typedef时,将前面的内容引入混乱,例如:

typedef int* IntPtr;
const IntPtr p1;   // same as int* const p1;
Run Code Online (Sandbox Code Playgroud)

如果您的编码标准允许使用typedef指针,那么它确实应该坚持将const放在类型之后.在每种情况下,但是当应用于类型时,const必须遵循它所适用的内容,因此一致性也支持const之后.但是,本地编码指南胜过所有这些; 差异通常不足以返回并更改所有现有代码.

  • 我的政策(当我独自决定时)是将 const 放在(为了连贯性)* 和* 之后,不使用指向指针的 typedef(或一般情况下的 typedef):-)。顺便说一句, string::iterator 与 string::const_iterator 也应该考虑到您的决定中。(只是为了混淆事物:-)。没有正确的答案。) (2认同)
  • @JamesKanze —请稍等,在这里帮助我...在发布的示例中我看不到混乱。除了“常量整数指针”(即“指向整数的常量指针”)以外,“ const IntPtr p1”还可能意味着什么?即使他们不知道如何定义IntPtr,也没有人会以为p1是可变的。而且,为什么有人会错误地认为`* p1'是不可变的?而且,将const放置在其他任何地方(例如,IntPtr const p1),根本不会改变语义。 (2认同)
  • @ToddLehman你可能没有看到混乱,但是大多数C++程序员都会这样做,并且系统地弄错了(毫无疑问,像`std :: vector <T> :: const_iterator`这样的东西,它不是迭代器,它是const ,但它指向的是什么). (2认同)

Nic*_*ate 6

有历史原因,左或右是可以接受的.Stroustrup在1983年之前已经将const添加到了C++中,但直到C89/C90它才进入C语言.

在C++中,有一个很好的理由始终在右边使用const.你会在任何地方保持一致,因为必须以这种方式声明const成员函数:

int getInt() const;
Run Code Online (Sandbox Code Playgroud)


Mac*_*ark 5

C 使用从右到左的语法。只需从右到左阅读声明:

int var = 0;

// one is a pointer to a const int
int const * one = &var; 
// two is a pointer to an int const (same as "const int")
const int * two = &var; 

// three is a constant pointer to an int
int * const three = &var;
Run Code Online (Sandbox Code Playgroud)

留给“const”的第一件事就是受它的影响。

如需更多乐趣,请阅读本指南:http : //cseweb.ucsd.edu/~ricko/rt_lt.rule.html