【问题标题】:Is initializing char array from string literal considered to be a implicit conversion?从字符串文字初始化 char 数组是否被认为是隐式转换?
【发布时间】:2023-03-27 21:36:01
【问题描述】:

char x[10] = "banana"; 被认为是从const char[7]char[10] 的隐式转换?

由于std::is_convertible<const char[7], char[10]>::value 的计算结果为false,显而易见的答案是它不是,但我在任何地方都找不到隐式转换的正确定义。阅读cppreference我会说这是因为:

每当某种类型的表达式时,都会执行隐式转换 T1 用于不接受该类型的上下文,但接受一些 其他类型 T2;特别是:......当初始化一个新对象时 类型 T2,包括返回 T2 的函数中的 return 语句;

虽然我不确定他们为什么没有从这个案例中排除显式构造函数。

后续问题(可能没用):

数组是否完全排除在任何类型的转换(即数组到数组的转换)之外?

【问题讨论】:

  • 数组是否完全排除在任何类型的转换之外?您真的没有听说过数组到指针的转换吗?
  • @LanguageLawyer 我的意思是数组到数组的转换。我将编辑我的问题。
  • 这是聚合初始化,请参见 字符数组 - en.cppreference.com/w/cpp/language/aggregate_initialization 没有发生转换。
  • @RichardCritten 这是聚合初始化你确定 cppreference 调用它聚合初始化是正确的吗?
  • 跟进 - 字符数组的声明和初始化在标准dcl.init.string 中有自己的部分

标签: c++ initialization language-lawyer declaration implicit-conversion


【解决方案1】:

从语言上讲,从字符串字面量初始化 char 数组是一种隐式转换。

[conv.general]:

表达式 E 可以隐式转换为类型 T 当且仅当声明 T t=<i>E</i>; 格式正确时,对于某些发明的临时变量t ([dcl.init])。

请注意,核心语言只定义了从表达式到类型的隐式转换。所以“从const char[7]隐式转换到char[10]”的含义是不确定的。

只要To 是数组类型,is_convertible&lt;From, To&gt;::value 就是false,因为如果To 不是有效的返回类型(而数组不是),则它被定义为生成false。 (这可以通过不同的方式实现。)

[meta.rel]/5:

当且仅当以下代码中的返回表达式格式正确时,模板特化is_­convertible&lt;From, To&gt; 的谓词条件才会满足,包括对函数返回类型的任何隐式转换:

To test() {
  return declval<From>();
}

数组很少是隐式转换的目标,因为它们既不是参数类型也不是返回类型。但他们并没有被排除在temporary materialization conversion之外。

【讨论】:

  • "从字符串字面量初始化 char 数组是一种隐式转换" - 这感觉不对。字符数组可以写成char x[10] = {'b', 'a', 'n', 'a', 'n', 'a', '\0' };char x[10] = "banana";,它们都会导致聚合(数组)初始化。我没有看到转换。
  • @TedLyngmo 我说的是“语言律师”。在实践中没关系。
  • 我的意思也是一种“语言律师”的方式 :-) 字符串文字只是提供了另一种初始化字符数组的方式。
  • @TedLyngmo 该标准根据(复制)初始化定义了隐式转换。所以根据标准,即使是最奇怪的初始化也是隐式转换。尽管它在实践中可能并不直观或没有意义。
  • 人们永远不知道这些知识什么时候会派上用场。谢谢:-)
【解决方案2】:

在此声明中

char x[10] = "banana";

没有转换。字符串文字的元素用于初始化数组的元素。其实就等价于

char x[10] = { 'b', 'a', 'n', 'a', 'n', 'a', '\0' };

如果你声明一个指针而不是数组

const char *x = "banana";

然后具有const char[7] 类型的字符串文字将被隐式转换为指向其类型为const char * 的第一个元素的指针。

上面的声明等价于

const char *x = &"banana"[0];

【讨论】:

  • 为清楚起见,我认为您的第一句话应该以“没有转换”或“既没有隐式也没有显式转换”结尾
【解决方案3】:

我没有最新标准的副本,但是在[dcl.init.string]中,有一段:

如果初始化器的数量少于数组元素的数量,则未显式初始化的每个元素都应进行零初始化 (8.5)。
C++.2011§8.5.2¶3

因此,这是使用文字初始化已知大小的 char 数组的指定行为。

【讨论】:

  • 抱歉,这能回答我的问题吗?我找不到连接。
  • 您的第一个问题。它的回答是否定的。
  • 数组没有用赋值初始化,所以我不确定你想要什么来回答你的后续问题。
  • 我很困惑。你是说它被认为是隐式转换吗?
  • "不是隐式转换,而是标准中专门描述的初始化。"
【解决方案4】:

出于重载决议的目的,它被认为是一种隐式转换,但不涉及实际转换(身份转换序列)。见[over.ics.list]/4:

否则,如果参数类型是字符数组125 并且初始化列表有一个元素是 适当类型的string-literal(9.4.2),隐式转换序列是恒等转换。

125 由于没有数组类型的参数,这只会作为引用参数的被引用类型出现。

到数组类型本身的隐式转换(不是对数组的引用)似乎受到很大限制:它显然只允许在变量定义中使用。像 static_cast&lt;char[10]&gt;("banana") 这样的东西不会编译(至少在 GCC 和 Clang 上)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-15
    • 2021-03-09
    • 1970-01-01
    • 2021-08-26
    • 1970-01-01
    • 2015-08-12
    相关资源
    最近更新 更多