const int *p 与 int const *p - 类型后面的 const 是否可以接受?

发布于 2024-07-24 09:28:26 字数 1192 浏览 6 评论 0原文

我的同事对他启发的问题的得分是 0 比 2 (1< /a>,2),所以我想我应该给他一个机会跟上来。

我们最新的分歧是关于在声明中放置“const”的样式问题。

他认为它应该位于类型前面或指针后面。 原因是,这通常是其他人所做的,而其他风格很容易令人困惑。 因此,指向常量 int 的指针和指向 int 的常量指针将分别是:

const int *i;
      int * const i;

但是,我还是很困惑。 我需要一致且易于理解的规则,而我理解“const”的唯一方法是它位于它正在修改的内容之后。 有一个例外允许它位于最终类型之前,但那是一个例外,所以如果我不使用它,对我来说会更容易。

因此,指向常量 int 的指针和指向 int 的常量指针分别是:

int const * i;
int * const i;

作为一个额外的好处,以这种方式执行操作可以使更深层次的间接更容易理解。 例如,指向 int 的常量指针的指针显然是:

int * const * i;

我的论点是,如果有人按照自己的方式学习它,他们将很容易弄清楚上面的结果。

这里的最终问题是,他认为将 const 放在 int 后面是难以形容的丑陋,并且对可读性非常有害,因此应该在样式指南中禁止它。 当然,我认为指南应该建议按照我的方式进行,但无论哪种方式,我们都不应该禁止一种方法。

编辑: 我得到了很多好的答案,但没有一个真正直接解决我的最后一段(“最终问题”)。 很多人都主张一致性,但在这种情况下,这是否如此理想,以至于最好禁止其他实现方式,而不是仅仅阻止它?

My co-worker is 0 for 2 on questions he has inspired (1, 2), so I thought I'd give him a chance to catch up.

Our latest disagreement is over the style issue of where to put "const" on declarations.

He is of the opinion that it should go either in front of the type, or after the pointer. The reasoning is that this is what is typically done by everyone else, and other styles are liable to be confusing. Thus a pointer to a constant int, and a constant pointer to int would be respectively:

const int *i;
      int * const i;

However, I'm confused anyway. I need rules that are consistent and easy to understand, and the only way I can make sense of "const" is that it goes after the thing it is modifying. There's an exception that allows it to go in front of the final type, but that's an exception, so it's easier on me if I don't use it.

Thus a pointer to a constant int, and a constant pointer to int would be respectively:

int const * i;
int * const i;

As an added benefit, doing things this way makes deeper levels of indirection easier to understand. For example, a pointer to a constant pointer to int would clearly be:

int * const * i;

My contention is that if someone just learns it his way, they'll have little trouble figuring out what the above works out to.

The ultimate issue here is that he thinks that putting const after int is so unspeakably ugly, and so harmful to readability that it should be banned in the style guide. Of course, I think if anything the guide should suggest doing it my way, but either way we shouldn't be banning one approach.

Edit:
I've gotten a lot of good answers, but none really directly address my last paragraph ("The ultimate issue"). A lot of people argue for consistency, but is that so desirable in this case that it is a good idea to ban the other way of doing it, rather that just discouraging it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

凝望流年 2024-07-31 09:28:26

最重要的是一致性。 如果没有任何编码指南,那么选择一个并坚持使用。 但是,如果您的团队已经有了事实上的标准,请不要更改它!

也就是说,我认为到目前为止更常见的是

const int * i;
int * const j;

因为大多数人都写

const int n;

而不是

int const n;

旁注 - 读取指针常量的一种简单方法是从右侧开始读取声明。

const int * i; // pointer to an int that is const
int * const j; // constant pointer to a (non-const) int
int const * aLessPopularWay; // pointer to a const int

The most important thing is consistency. If there aren't any coding guidelines for this, then pick one and stick with it. But, if your team already has a de facto standard, don't change it!

That said, I think by far the more common is

const int * i;
int * const j;

because most people write

const int n;

instead of

int const n;

A side note -- an easy way to read pointer constness is to read the declaration starting at the right.

const int * i; // pointer to an int that is const
int * const j; // constant pointer to a (non-const) int
int const * aLessPopularWay; // pointer to a const int

有一类示例将 const 放在类型右侧也有助于避免混淆。

如果 typedef 中有指针类型,则无法将类型的常量更改为

typedef int * PINT;
const PINT pi;

pi仍然具有类型int * const< /code>,无论你在哪里编写const,这都是一样的。

There's a class of examples where putting the const on the right of the type also helps avoid confusion.

If you have a pointer type in a typedef, then it is not possible to change the constness of the to type:

typedef int * PINT;
const PINT pi;

pi still has the type int * const, and this is the same no matter where you write the const.

剩一世无双 2024-07-31 09:28:26

我希望 B. Stroustrup 关于 Style & 的常见问题解答对此做出解释。 技术会给你明确的答案。

Bjarne Stroustrup 的 C++ 风格和技术常见问题解答


我个人更喜欢:

int const* pi;
int* const pi;

因为 const 标识左侧标记,该标记应为常量。

当你使用这样的东西时,你肯定会保持相同的一致性:

int const* const pi;

而不是不一致地写:

const int* const pi;

如果你有一个指向指针的指针等等,会发生什么:

int const* const* const pi;

而不是:

const int* const* const pi;

I hope this explanation from B. Stroustrup's FAQ on Style & Techniques will give you a definite answer.

Bjarne Stroustrup's C++ Style and Technique FAQ


I personaly prefer:

int const* pi;
int* const pi;

Because const identifies the left token which is intended to be const.

And you definitely keep the same consistency when using smth like that:

int const* const pi;

Instead of writing inconsistently:

const int* const pi;

And what happens if you have a pointer to pointer and so on:

int const* const* const pi;

Instead of:

const int* const* const pi;
你好,陌生人 2024-07-31 09:28:26

我参加了一次会议,Bjarne Stroustrup 正在做演讲,他使用了类似 const int* i 的东西。 有人问他为什么用这种风格,他回答(释义):

“当某些东西是常量时,人们喜欢首先看到 const。”

I was at a conference where Bjarne Stroustrup was giving a presentation, and he used something like const int* i. Someone asked him why does he use this style and he responded (paraphrasing):

"people like to see const first when something is constant."

初吻给了烟 2024-07-31 09:28:26

人们通常使用 const int* blah ,因为它读起来很好英语。 我不会低估它的用处。

我发现 int* const blah 变体非常罕见,因此向后进行更常见的定义通常没有用处。 一般来说,我不喜欢任何在一般情况下稍微模糊代码的东西,尽管它可能在特殊情况下提供一些名义上的好处。

另请参见“if (1 == a)”。 有些人真的很喜欢编写读起来不像英语的代码。 我不是那些人中的一个。

但实际上,const 背后的规则很简单。 向左看,然后向右看。 如此简单,我认为在风格指南中不值得太多关注。

People typically use const int* blah because it reads well as English. I wouldn't underestimate the usefulness of that.

I find that the int* const blah variation is rare enough that it's not typically useful to make the more common definition backwards. I am, in general, not a fan of anything that even slightly obscures code in the general case, though it might provide some nominal benefit in the exceptional case.

See also "if (1 == a)". Some people really enjoy writing code that doesn't read as English. I am not one of those people.

Really, though, the rules behind const are simple. Look to the left, then to the right. So simple that I wouldn't think it's worth much attention in a style guide.

超可爱的懒熊 2024-07-31 09:28:26

如果只是变量和指向它们的指针可以是 const 或不是 const,那么可能就没有那么重要了。 但请考虑一下:

class MyClass
{
    public:
        int foo() const;
};

除了尾随它所引用的函数之外,const 不可能写在其他任何地方。

风格指南越短,开发人员就越有可能遵循它。 可能的最短规则,以及为您提供一致性的唯一规则是:

const 关键字始终尾随 无论它指的是什么。

所以,我会为你的同事说 0:3。

关于你的“最终问题”:为了风格指南的缘故,指南是否“劝阻”或“禁止”它公开反对的事物并不重要。 这是一个社会问题,一个政策。 风格指南本身应该尽可能简洁。 冗长的风格指南只会被每个人忽视(除了管理人员寻找应受指责的人),因此只需写“做”或“不做”,并在其他地方(例如在公司政策中)说明您对违反指南的行为同行评审的进行方式)。

If it were only variables and pointers to them that could be const or not, it would probably not matter that much. But consider:

class MyClass
{
    public:
        int foo() const;
};

No way that const could be written anywhere else but trailing the function it refers to.

The shorter a style guide, the more likely developers will follow it. And the shortest rule possible, and the only rule that will give you consistency, is:

The const keyword always trails whatever it is referring to.

So, I'd say 0:3 for your coworker here.

Regarding your "ultimate issue": For the sake of the style guide, it does not matter whether the guide "discourages" or "bans" the things it speaks out against. That is a social issue, a policy. The style guide itself should be as crisp and short as possible. Long style guides just get ignored by everybody (except management on the lookout for someone to blame), so just write "do" or "don't", and state what you do with violations of the guide elsewhere (e.g. in the company policy of how peer reviews are being done).

江城子 2024-07-31 09:28:26

虽然 const intint const 之间没有任何有意义的区别(并且我已经看到这两种样式都在使用),但 const int *< 之间存在差异/code> 和 int * const

在第一个中,您有一个指向 const int 的指针。 您可以更改指针,但无法更改它指向的值。 在第二个中,你有一个指向 int 的 const 指针。 您无法更改指针(希望它已根据您的喜好进行初始化),但您可以更改所指向的 int 的值。

正确的比较是与 const int * 和 int const * 进行比较,它们都是指向 const int 的指针。

请记住,* 不一定按您希望的方式工作。 声明 int x, y; 将按照您的预期工作,但 int* x, y; 声明一个指向 int 的指针和一个 int。

While there is no meaningful difference between const int and int const (and I've seen both styles in use), there is a difference between const int * and int * const.

In the first, you have a pointer to a const int. You can change the pointer, but you can't change the value it points to. In the second, you have a const pointer to int. You can't change the pointer (hope it's initialized to your liking), but you can change the value of the pointed-to int.

The proper comparison is with const int * and int const *, which both are pointers to a const int.

Remember that the * doesn't necessarily work as you might like. The declaration int x, y; will work as you expect, but int* x, y; declares one pointer to int, and one int.

撕心裂肺的伤痛 2024-07-31 09:28:26

一旦您训练自己从右向左阅读 C++ 类型声明,将“const”放在类型声明之后就变得更有意义。

我要把你的牛人定为 0 换 3 :)

Putting "const" after the type declaration makes a whole lot more sense once you train yourself to read your C++ type declarations from right to left.

I'm going to peg your cow-orker at 0-for-3 :)

罗罗贝儿 2024-07-31 09:28:26

就我个人而言(这是个人偏好),我发现从右到左阅读类型声明是最简单的。 尤其是当你开始将参考文献混入其中时。

std::string const&  name = plop; // reference to const string.

const std::string&  flame =plop; // reference to string const;
                                 // That works better if you are German I suppose :-)

Personally I (and it is a personal preeference) I finding reading type declarations from right to left the easiest. Especially when you start throwing references into the mix.

std::string const&  name = plop; // reference to const string.

const std::string&  flame =plop; // reference to string const;
                                 // That works better if you are German I suppose :-)
清风不识月 2024-07-31 09:28:26

这里的最终问题是,他认为将 const 放在 int 后面是难以形容的丑陋,并且对可读性非常有害,因此应该在样式指南中禁止它

真的吗?

向我展示一个在看到以下内容时陷入困境的程序员:

int foo() {
}

vs

int foo()
{
}

...,我将向你展示一个对细节不够关注的程序员。

任何称职的专业程序员都不会因为风格上的表面差异而烦恼。

编辑:确实 const int* 和 int* const 并不意味着完全相同的事情,但这不是重点。 OP 同事提出的观点是,风格的差异使得代码难以理解和理解。 维持。 我不同意这种说法。

The ultimate issue here is that he thinks that putting const after int is so unspeakably ugly, and so harmful to readability that it should be banned in the style guide

Really?

Show me a programmer who gets bogged down when he sees:

int foo() {
}

vs

int foo()
{
}

...and I'll show you a programmer who doesn't pay close enough attention to detail.

No professional programmer worth his salt will have a problem with superficial differences in style.

EDIT: It is true that const int* and int* const don't mean exactly the same thing, but that wasn't the point. The point made by OP's coworker was that differences in style make code difficult to understand & maintain. It is this claim I disagree with.

寂寞清仓 2024-07-31 09:28:26

让我把我的 2 美分投入到讨论中。

在现代 C++ 中,我建议坚持使用 int const 而不是 const int 以突出 constconstexpr 之间的区别代码>. 这将帮助程序员记住 const int 不能总是被认为是编译时常量,因为:

Let me put my 2¢ into the discussion.

In modern C++ I'd recommend to stick to int const instead of const int to highlight the difference between const and constexpr. It would help programmer to remember that const int cannot be always thought as compile-time constant, because:

  • compiler may (will?) allocate memory for it,
  • this memory may even be not write-protected (stack segment),
  • such a constant cannot serve all the duties constexpr can.
已下线请稍等 2024-07-31 09:28:26

规则是很好遵守的。 规则越简单越好。
Const 位于 const 的右侧。

采取这个声明:

int
主要的
( int 常量 argc
, char const * const * const argv

...

Rules are good to follow. Simpler rules are better.
Const goes to the right of what's const.

Take this declaration:

int
main
( int const argc
, char const * const * const argv
)
...

暮色兮凉城 2024-07-31 09:28:26

我同意你们俩的观点。 您应该将 cons 放在类型后面。 我还发现看着它是一种必须被摧毁的可憎行为。 但我最近对 ​​常量值参数 的奇迹的尝试让我明白了为什么要把const 第二个有意义。

int *
int const *
int * const
int const * const

光是看着就让我脖子上的汗毛都竖起来了。 我确信这会让我的同事感到困惑。

编辑:我只是想知道如何在类中使用它:

class Foo {
    Bar* const bar;
    Foo(const Foo&) = delete; // would cause too many headaches
public:
    Foo() : bar(new Bar) {}
    ~Foo() { delete bar; }
};

此示例中的 bar 在功能上等同于 Bar& 但它位于堆上并且可以删除。 在每个 Foo 的生命周期中,都会有一个与其关联的 Bar。

I agree with both of you. You should put the const after the type. I also find looking at it an abomination that must be destroyed. But my recent foray into the wonders of const value parameters has made me understand why putting the const second makes sense.

int *
int const *
int * const
int const * const

Just looking at that has the hairs on my neck standing. I'm sure it would confuse my co-workers.

EDIT: I was just wondering about using this in classes:

class Foo {
    Bar* const bar;
    Foo(const Foo&) = delete; // would cause too many headaches
public:
    Foo() : bar(new Bar) {}
    ~Foo() { delete bar; }
};

bar in this example is functionally equivalent to Bar& but it is on the heap and can be deleted. For the lifetime of each Foo, there will be a single Bar associated with it.

壹場煙雨 2024-07-31 09:28:26

我喜欢使用以下形式声明“清单常量”。 在本例中,值本身是一个常量,因此我将“const”放在前面(与 Bjarne 相同)以强调这一点常量应该在编译时显现出来,并且可用于编译器的特定优化。

const int i = 123;

为了声明不会用于修改值的引用,我使用以下形式,强调标识符是“常量引用”这一事实。 参考值可以是也可以不是常数。 [相关讨论:如果函数参数不是指针或引用,您还会使用“const”吗? 使用“const”作为函数参数]

void fn( int const & i );

对于指针,我使用相同的我用于引用的形式,本质上是出于相同的原因(尽管术语“常量指针”似乎比“常量引用”更加模糊)。

void fn( int const * i );

此外,正如另一位发帖者指出的那样,当您具有多个间接级别时,这种形式保持一致。

void fn( int const * const * i );

最后一种情况,即声明一个常量指针,在我的 C++ 经验中很少见。 无论如何,你在这里真的没有任何选择。 [此案例表明,最一致的方法是将单词“const”放在类型之后 - 因为事实上,这是此特定声明的必需。 ]

void fn( int * const i );

...除非你使用 typedef。

typedef int * IntPtr;

void fn1( const IntPtr i );
void fn2( IntPtr const i );

最后一点:除非您在低级域中工作,否则大多数 C++ 代码应该永远不要声明指针。 因此,这个讨论的这个方面可能与 C 更相关。

I like to to use the following form for declaring "manifest constants". In this case, the value itself is a constant so I put the "const" first (same as Bjarne) to emphasize that the constness should be manifest at compile-time, and usable as such for specific optimizations by the compiler.

const int i = 123;

For declaring references which will not be used to modify the value, I use the following form which emphasizes the fact that the identifier is a "constant reference". The referenced value may or may not be a constant. [Related discussion: Would you even be using "const" for function parameters if they were not pointers or references? Use of 'const' for function parameters]

void fn( int const & i );

For pointers, I use the same form that I use for references, for essentially the same reason (although the term "constant pointer" seems a little more ambiguous than "constant reference").

void fn( int const * i );

Also, as another poster noted, this form remains consistent when you have multiple levels of indirection.

void fn( int const * const * i );

The final scenario, where you are declaring a pointer which is constant is pretty rare in my experience with C++. In any case, you don't really have any choices here. [This case demonstrates that the most consistent approach would be to put the word "const" after the type -- since that is, in fact, required for this particular declaration.]

void fn( int * const i );

...unless you use a typedef.

typedef int * IntPtr;

void fn1( const IntPtr i );
void fn2( IntPtr const i );

One final note: Unless you are working in a low-level domain, most C++ code should never declare a pointer. Therefore, that aspect of this discussion is probably more relevant to C.

别把无礼当个性 2024-07-31 09:28:26

在现代 C++11 中,您还可以使用模板 typedef 来增加复杂声明的清晰度:

template<typename T>
using Const = const T;

template<typename T>
using Ptr = T*;

您在问题中提到的三个声明:

int const * a;
int * const b;
int * const * c;

然后将写为:

Ptr<Const<int>> a;
Const<Ptr<int>> b;
Ptr<Const<Ptr<int>>> c;

In modern C++11, you could also use template typedefs to add clarity to complicated declarations:

template<typename T>
using Const = const T;

template<typename T>
using Ptr = T*;

The three declarations you mentioned in your question:

int const * a;
int * const b;
int * const * c;

would then be written as:

Ptr<Const<int>> a;
Const<Ptr<int>> b;
Ptr<Const<Ptr<int>>> c;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文