【问题标题】:Why const for implicit conversion?为什么要使用 const 进行隐式转换?
【发布时间】:2011-04-23 04:16:48
【问题描述】:

在大量阅读ISO/IEC 14882, Programming language – C++ 之后,我仍然不确定为什么需要const 来隐式转换为具有如下单参数构造函数的用户定义类型

#include <iostream>

class X {
public:
   X( int value ) {
      printf("constructor initialized with %i",value);
   }
}

void implicit_conversion_func( const X& value ) {
   //produces "constructor initialized with 99"
}

int main (int argc, char * const argv[]) {
   implicit_conversion_func(99);
}



从第 4 节第 3 行开始

表达式 e 可以隐式转换为类型 T 当且仅当声明 T t=e;对于一些发明的临时变量 t (8.5) 是良构的。某些语言结构要求将表达式转换为布尔值。出现在这种上下文中的表达式 e 被称为在上下文中转换为 bool 并且当且仅当声明 bool t(e);对于一些发明的临时变量 t (8.5) 是良构的。任一隐式转换的效果与执行声明和初始化,然后使用临时变量作为转换的结果相同。如果 T 是左值引用类型 (8.3.2),则结果为左值,否则为右值。当且仅当初始化将其用作左值时,表达式 e 才用作左值。

随后我在 8.5 第 6 行中找到了与用户定义类型相关的初始化程序部分

如果程序要求对 const 限定类型 T 的对象进行默认初始化,则 T 应是具有用户提供的默认构造函数的类类型。

最后,我在 12.3 第 2 行结束了关于用户定义转换的说明

用户定义的转换仅适用于明确的情况(10.2、12.3.2)。

不用说,10.2 和 12.3.2 没有回答我的问题。

  1. 有人能解释一下const 对隐式转换的影响吗?
  2. const 的使用是否使转换在 12.3 第 2 行“明确”?
  3. const 是否会影响第 4 节中讨论的左值和右值?

【问题讨论】:

  • 你不只是喜欢 C++ 吗?

标签: c++ constructor constants implicit-conversion rvalue


【解决方案1】:

这与转换是隐式并没有太大关系。此外,它与转换 并没有太大关系。这真的是关于 rvalueslvalues

当您将99 转换为X 时,结果是一个右值。在 C++ 中,转换的结果始终是右值(除非您转换为引用类型)。在 C++ 中,将非常量引用附加到右值是非法的。

例如,这段代码不会编译

X& r = X(99); // ERROR

因为它试图将非常量引用附加到右值。另一方面,这段代码很好

const X& cr = X(99); // OK

因为将 const 引用附加到右值是完全可以的。

同样的事情也会发生在您的代码中。它涉及隐式转换的事实有点无关紧要。您可以用显式替换隐式转换 一个

implicit_conversion_func(X(99));

并以同样的情况结束:使用const 编译,没有const 它没有。

同样,转换(显式或隐式)在这里扮演的唯一角色是它帮助我们产生一个右值。通常,您可以通过其他方式生成右值并遇到相同的问题

int &ir = 3 + 2; // ERROR
const int &cir = 3 + 2; // OK

【讨论】:

  • "当你将 99 转换为 X 类型时,结果是一个右值。" 不。右值是一个表达式。 转换99X 会产生一个临时对象。
  • @curiousguy:虽然“右值”的概念与表达式紧密相连,但“右值”一词可以用来指代表达式本身以及它产生的结果。语言标准实际上比“右值表达式”更频繁地使用“右值结果”的概念。 (显然,两者实际上都是指同一件事)。此外,语言规范在 5.2.3 中清楚明确地指出,函数式 case 的结果是一个右值。时期。它也恰好是“临时对象”这一事实与此无关。
  • 你能解释一下“右值”是什么意思吗?
  • 除非你转换成引用类型”你的意思是:如果你转换成引用类型?
  • @curious 将 99 转换为类型 X 是第 4 条第 3 段意义上的右值:“如果 T 是左值引用类型或右值引用,则结果是左值函数类型(8.3.2),如果 T 是对对象类型的右值引用,则为 xvalue,否则为 prvalue。”。确实,右值是一个表达式。但表达式并不总是源代码。表达式可以通过语言语义合成。
【解决方案2】:

根据第 5.2.2 节第 5 节,当函数的参数是 const 引用类型时,如果需要,会自动引入临时变量。在您的示例中,必须将X(99) 的右值结果放入一个临时变量中,以便该变量可以通过const 引用传递给implicit_conversion_func

【讨论】:

  • "必须将右值 99 放入一个临时变量中,以便该变量可以通过 (const) 引用传递给 X 的构造函数" 否。构造函数是按值传递的;没有对 int 的常量引用,也没有值为 99 的临时变量。“在那里创建非常量临时变量的语义无论如何都会相当混乱std::string() = "Hello, world" 怎么样?
  • @curiousguy 好点——我想我误读了 OP。临时是 const X,通过使用 99 作为参数构造初始化,而不是 const int。但是,它的要点仍然存在:创建一个 const 临时以满足 const &amp; 参数。
猜你喜欢
  • 2020-07-20
  • 2018-02-05
  • 1970-01-01
  • 1970-01-01
  • 2021-06-01
  • 2013-03-20
  • 1970-01-01
  • 2012-07-09
  • 2018-10-29
相关资源
最近更新 更多