为什么有些人更喜欢"T const&"而不是"const T&"?

Mic*_*yan 56 c++ syntax types pointers reference

因此,我意识到const T&并且T const&它们是相同的并且都意味着对const T的引用.在这两种情况下,引用也是常量的(与指针不同,引用不能被重新分配).我观察到,在我有点经验的情况下,大多数C++程序员都会使用const T&,但我遇到过一些使用过的人T const&.我const T&之所以使用它只是因为我学到了这一点,所以T const&对我来说看起来有点滑稽.您使用您使用的变体的原因是什么?你们中的任何一个人是否在一个组织工作,其编码标准要求使用一种变体而不是另一种变体?

编辑
根据答案,看来在两者之间进行选择的一个原因是你是想要像编译器(从右到左)还是像英语(从左到右)那样阅读它.如果像编译器一样读取它,则"T const&"读作"&(引用)const(到常量)T(类型T)".如果从左到右读取它像英语,则"const T&"被读作"以引用形式存在的T类型的常量对象".我更喜欢像英文散文一样阅读它,但我当然可以通过编译器的方式来理解它.

没有人回答组织或编码标准问题,但我强烈怀疑大多数组织不会强制要求一个,尽管他们可能会努力保持一致性.

Unc*_*ens 44

我想有些人只是喜欢从右到左阅读声明.const适用于左侧令牌,除非那里没有任何东西,并且它适用于右侧令牌.因此const T&涉及"除外" - 使用并且可能被认为更复杂(实际上两者都应该易于理解).

相比:

const T* p;  (pointer to T that is const)
T const* p;  (pointer to const T) //<- arguable more natural to read
T* const p;  (const pointer to T)
Run Code Online (Sandbox Code Playgroud)

  • @Michael,尽管写了"T const",我仍然从左到右阅读声明.所以我说"T const"而不是"const T". (3认同)

Tom*_*mek 26

当你有一个以上的const/volatile修饰符时,这会有所不同.然后将它放在类型的左边仍然有效,但会破坏整个声明的一致性.例如:

T const * const *p;
Run Code Online (Sandbox Code Playgroud)

意味着p是指向const T的const指针的指针,并且你从右到左一致地读取.

const T * const *p;
Run Code Online (Sandbox Code Playgroud)

意味着相同,但一致性丢失,你必须记住,最左边的const/volatile只与T绑定,而不是T*.

  • 如果有人做了"T const",然后有其他人出现了`const T`,并且意外地改变了一些东西:`const T const*const p`,编译器回复`错误:你想要它是怎样的常量?` (6认同)

Lar*_*olm 7

如果你觉得这个讨论很有趣,你可能会发现Dan Saks的这篇文章很有趣.它没有直接解决你的问题,但解释了为什么他更喜欢

VP const foo[];
Run Code Online (Sandbox Code Playgroud)

const VP foo[];
Run Code Online (Sandbox Code Playgroud)

这是因为给定的

typedef void *VP;
Run Code Online (Sandbox Code Playgroud)

你很容易误以为上面的第二个例子意味着

const void *foo[];  // Wrong, actually: void *const foo[];
Run Code Online (Sandbox Code Playgroud)

但第一个例子更难以曲解.


Edw*_*nge 5

我的推理如下:

如果你写“const T&”,它似乎确实更好地滚出舌头,但当你这样做时,你最终会得到模棱两可的“常量T引用”。我已经不止一次看到这在代码的可理解性方面导致问题,这使得即使是半经验的人也可以误解某些东西的含义或如何声明更复杂的类型。

我现在想不出任何例子,但我不止一次回答了关于类型声明和常量的问题,其中问题是由使用“const T &”而不是“T const &”的习惯引起的。我以前也是这样写的,当我成为高级开发人员,负责指导和创建项目代码标准的人时,我发现当我强迫每个人都使用“T const&”时,对于入门级开发人员来说要容易得多。我想一个相当微不足道的新手错误是为什么这段代码编译?


const T* t = f();
t = 0; // assignment to const?? - no, it is not the T* that is const, just the T.
Run Code Online (Sandbox Code Playgroud)

当您学会按照编译器的方式阅读它时,就会更容易理解任何给定的复杂类型,并允许您在需要时更容易地声明复杂类型。对于复杂类型,我指的是以下内容:

T 常量 * 常量 &

当你知道编译器从右到左、从里到外读取时,这意味着什么就变得很明显了,当需要编写一个时,你可以很容易地做到:引用指向常量 T 的常量指针。现在编写 a 的声明“对指向 T 的常量指针的指针的引用”。如果你只是使用从左到右的符号,我想你会发现这很容易。

简而言之,尽管最初自学一直使用右->左语法似乎不自然,而不是仅在需要时(因为经常这样做),但您会发现记住一行代码的含义要容易得多以及如何写出你的意思。这与我在声明中不允许使用“,”的原因大致相同:


T* ptr1 = 0, ptr2 = 0; // oops!!!

// do it this way please! T* ptr1 = 0; T* ptr2 = 0;

Run Code Online (Sandbox Code Playgroud)

从技术上讲,一切都是一样的,但是当你试图让一群不同能力的人做同样的事情时,你会倾向于确保每个人都使用最容易理解和使用的方法。我的经验告诉我“T const&”就是那种方法。