【问题标题】:Shouldn't "const references" be actually called "references to const"?“const 引用”实际上不应该称为“对 const 的引用”吗?
【发布时间】:2019-10-27 13:42:35
【问题描述】:

我在玩 constexpr 引用时产生了这种感觉。但问题本身与 constexpr 无关,只是它所揭示的。

我们知道有“指向 const 的指针”和有“const 指针”。顺便说一句,由于后者的使用比前者少得多,因此它们的名称实际上通常用于引用前者。无论如何,引用没有这种区别,因为它们不可重新绑定。因此,我们只有“const 引用”而不是“const 引用”。这是通用术语,标准中也是is used。但这对我来说似乎不对。

让我们看一些著名的例子,用这个常见的术语进行评论:

      int    i = 0;   // Value
      int*  pi = &i;  // Pointer to i
const int* cpi = &i;  // Pointer to const i
int const* cpi = &i;  // Pointer to const i (east-const style)
int* const pci = &i;  // Const pointer to i
      int&  ri = i;   // Reference to i
const int& rci = i;   // Const reference to i
int const& rci = i;   // Const reference to i (east-const style)

现在让我们仔细看看上面的几行:

const int* cpi = &i;  // Pointer to const i
const int& rci = i;   // Const reference to i

const int* 声明“指向 const 的指针”,而 const int& 声明“const 引用”。声明中的顺序相同,含义中的顺序不同。这里有一个明显的矛盾。但是,如果我们称其为“对 const 的引用”,则不一致就消失了。两边的顺序一样。

随着constexpr的引入,紧张局势加剧:

constexpr int& cri = i;  // Constexpr reference to i
constexpr const int& crci = i;  // Constexpr const reference to i

“Consexpr const”参考?嗯?文档clearly says

对象声明中使用的constexpr 说明符暗示const

引用是一个对象。那么,当 const 已经是 constepxr 时,为什么我们还需要它呢?但是,如果 i 是 const,我们还需要它。看起来很沮丧。

但是在“引用 const”的帮助下,挫败感不再存在。让我们调用crci“constexpr 对 const i 的引用”。现在很明显const 应用于被引用对象,而constexpr 应用于引用本身,说明它可以在 constexpr 上下文中使用。而且它是 const,因为所有引用都是 const。完全有道理。为了使其与指针更加一致,我们甚至可能使用了以下假设语法:

const int& constexpr crci = i;   // Constexpr reference to const i
const int* const      pci = &i;  // Const pointer to const i (perfect consistency)

但这不是 C++ 的工作原理,无论好坏。

“引用 const”这个概念真的帮助我理解了“constexpr const 引用”这个东西。

你怎么看? “引用 const”的概念听起来对您有说服力吗?

【问题讨论】:

  • 在这种情况下,我同意你的观点(如果我理解正确的话):命名应该命名为“引用 const int”的东西是一种不好的方式(一种令人困惑的方式)。
  • 魔鬼的拥护者:您可以将const int& 绑定到非const int
  • @VittorioRomeo 就像你可以将const int* 绑定到一个非常量整数一样。然而我们确实说“指向 const 的指针”。
  • 这是一个语言问题,但似乎不是关于C++语言的问题,而是关于英语的问题。在 C++ 中,无论在语义上还是句法上,它都作为“对 const 的引用”;人们只是不喜欢多余的音节。事实上,类似int & const r = i 的“常量指针”的并行构造不是有效构造。
  • @rustyx 更多魔鬼的宣传:至少存在一些混淆,因为我们有时会看到涉及惊喜的问题,例如T 是带有模板参数int& 的模板参数,const T 不是const int& 而是int&。尽管我们也看到了关于指针的类似问题,但尚不清楚更精确的语言是否或多少有助于避免这种混淆。

标签: c++ pointers language-lawyer constexpr


【解决方案1】:

是的,const int & 的正确名称是“对const int 的引用”。

它通常被称为“constint 的引用”(可能是因为这听起来更好一些),但从技术上讲,这是用词不当。

即使它们不可重新绑定,引用本身也永远不会是 const(即 std::is_const_v 始终等于 false 作为引用)。


constexpr const int& crci 

“Consexpr const”参考?嗯? ... 让我们称 crci “constexpr 对 const i 的引用”

没错,crci 是“constexpr 对 const i 的引用”。


为了使其与指针更加一致,我们甚至可能使用了以下假设语法:

const int& constexpr crci = i;   // Constexpr reference to const i
const int* const      pci = &i;  // Const pointer to const i (perfect consistency)

说实话,我看不出这个提议如何提高一致性。 int *constexpr pci; 不允许用于指针,那么为什么要允许它用于引用?

事情似乎一开始就相当一致:

constexpr const int *a; // constexpr (and const) pointer to const int
constexpr const int &a; // constexpr (but not const) reference to const int

是的,添加constexpr 本身不会引用const,但我认为不需要修复它。 (const 参考和非const 参考之间有什么区别?)

请注意,constexpr 不是类型的一部分,而是变量的属性。 (例如,constexpr int x; 声明 x 的类型为 const int,而不是一些假设的 constexpr int)。

【讨论】:

  • “但我认为不需要修复” - 我不建议修复标准,这只是一个说明性示例 :)
【解决方案2】:

由于 volatile 往往也很相关,因此该标准通常在规范性文本中使用“对 cv-(un)qualified 的引用”来涵盖这两个限定词,这符合您的偏好。

通过快速搜索,除了您引用的代码示例之外,该标准似乎在以下位置使用(非)const 引用,所有这些都在标准库规范中:

[container.node.observers]

key_type& key() const;

返回:对 ... 的非常量引用


[rand.req.adapt]

...表达式 a.base() 应该是有效的并且应该返回一个 const 引用 ...


[futures.shared.future

— (19.1) shared_future::get() 返回对 ... 的 const 引用

可以说,可以通过引用 const 来改进措辞。


在标准之外,使用了“对 const 的引用”。但是 const 引用也是如此,有时选择它可能是因为简洁。

事实上,指向 const 的指针通常也通俗地称为 const 指针,尽管其含义不明确,容易引起混淆。在引用的情况下,对于那些知道引用不能是顶级合格的人来说没有歧义。初学者不会知道这一点,所以在我看来,“引用 const”在介绍性材料中很重要。但是,const 引用用于表示同一事物的解释可能也是如此。

【讨论】:

  • 非常感谢您的回答!我接受了 HolyBlackCat 的回答,因为它还提到 std::is_const_vconstexpr 不是类型的一部分。恕我直言,这很有趣。
猜你喜欢
  • 2023-03-13
  • 1970-01-01
  • 2020-09-01
  • 1970-01-01
  • 2015-05-23
  • 1970-01-01
  • 2020-07-20
  • 1970-01-01
  • 2020-03-21
相关资源
最近更新 更多