【问题标题】:why auto i = same_const_variable could not deduce "const"?为什么 auto i = same_const_variable 不能推导出“const”?
【发布时间】:2015-08-21 00:54:02
【问题描述】:
const int ci = 10;
auto i = ci;  // i will be "int" instead of "const int"
i = 20;

我想知道为什么 auto 是为这种行为而设计的?

为什么类型 i 是 "int" 而不是 "c​​onst int" ?

这里有什么问题?

我认为理解为什么会帮助我们记住它

【问题讨论】:

  • 因为ci 的值是intauto 推导出inti
  • 那么为什么 auto &i = ci;推断 const int& ?
  • 因为要引用 const 对象,引用必须是 const。 auto i = ci; 正在制作副本,const 对象的副本不需要是 const。
  • @AbhinavGauniyal "value of ci" 值不是正确的 C++ 术语;你的意思是,转换为右值的结果?
  • @camino 你期待什么?

标签: c++ c++11 auto type-deduction


【解决方案1】:

auto 大多遵循与模板参数推导相同的类型推导规则。唯一的区别是 auto 在某些情况下会从 braced-init-list 推导出 std::initializer_list,而模板参数推导不会这样做。

从 N3337,§7.1.6.4 [dcl.spec.auto]

6   ... 为变量 d 推导出的类型是 推导的A 使用从函数调用(14.8.2.1)的模板参数推导规则确定,...

您观察到的行为与从函数调用推导类型时模板参数推导的行为相同

§14.8.2.1 [temp.deduct.call]

2   如果 P 不是引用类型:
— ...
— 如果 A 是 cv 限定类型,则 A 的类型的顶级 cv 限定符将被忽略以进行类型推导

因此,在

auto i = ci;

顶级const 限定符被忽略,i 被推断为int

当你写作时

auto& i = ci;

那么i 不再是引用类型并且上述规则不适用,所以const 限定符被保留。

【讨论】:

  • 那么为什么模板是为这种行为而设计的呢? :)
  • @camino 您正在制作新副本。为什么原件的简历资质会影响副本的资质?
  • @T.C.不错的双重否定:) 感谢您的修复
  • @camino "为什么模板是为这种行为而设计的?" - 这是一个单独的问题。将其作为一个单独的问题发布。 (虽然它可能跑题了,因为它问的是标准委员会的想法,除了标准委员会之外没有人能回答这个问题。)
  • @curiousguy 不是真的。在答案中已经解决了问题之后,在 cmets 中出现的链式派生问题是一个问题。为什么它真的发生是它基于模板类型推导。为什么模板类型推导这样做是一个相关但不同的问题。
【解决方案2】:

auto 本身意味着您需要一个新的、本地拥有的变量以及给定值的副本。 const-ness 不是价值的一部分。 intint,无论它是使用文字、命名常量、表达式还是非const 变量指定的。

auto i = 3,
     j = i,
     k = ci,
     m = 3 + 4; // All these variables are type int.

要获得推导类型的常量,您仍然可以使用auto const。这在声明中表达了如何使用变量。

const auto i = 3;

从 C++14 开始,还有 decltype(auto) 说明符,它将 decltype 应用于初始化程序,以复制给定变量。也许这正是你所期望的:

decltype(auto) i = ci; // i receives type const int.

Live demo.

decltype(auto) 不过有点棘手,除了与决定函数调用包装器的返回类型有关的最初目的之外,它几乎没有用例。除非有充分的理由,否则请选择 const autoconst int

另一种选择是使用转发参考,拼写为auto &&。这指的是初始化它的变量或值,无论它是什么。

auto && i = ci; // i receives type const int & and aliases ci.

这表达性和具体性较差,但可靠地将i 声明为ci 的别名。您尝试的另一件事是auto &,它类似但只允许形成对预先存在的变量的引用。

auto & i = ci; // i receives type const int & and aliases ci.

const int 变量的引用必须是const int & 类型,否则将允许非法修改。

【讨论】:

  • @curiousguy decltype(x)decltype((x)) 不同。这是一个可憎的并且它很棘手。但是,它的行为与问题中隐含的期望相同。
猜你喜欢
  • 1970-01-01
  • 2014-10-26
  • 1970-01-01
  • 1970-01-01
  • 2020-12-01
  • 2018-10-02
  • 2022-01-15
  • 1970-01-01
相关资源
最近更新 更多