【问题标题】:The difference of function assigning to variable in C and C++C和C++中函数赋值给变量的区别
【发布时间】:2016-03-22 14:29:16
【问题描述】:
#include <stdio.h>
int foo() { return 0; }
int a = foo();
int main() {
    return 0;
}

上面的代码不能编译,因为

来自第 3.5.7 节 C 标准的初始化:

具有静态存储持续时间的对象的初始化程序或具有聚合或联合类型的对象的初始化程序列表中的所有表达式都应为常量表达式。

#include <iostream>
int foo() { return 0; }
int a = foo();
int main() {
    return 0;
}

但是不知道为什么不用constexpr就可以用C++编译了

我想提一下,我的主要问题是为什么不用constexpr就可以在C++中编译它

【问题讨论】:

  • 所以基本上你在问,为什么你的冷却器可以冷却,为什么你的笔记本不能,对吧?
  • 尽管有相似之处,但它们是两种完全不同的语言,请始终牢记这一点!
  • @Olaf:你可能的意思是,为什么你可以do it in C++ 而不是C。
  • @callyalater 谢谢,这就是我问这个问题的原因。看来我的表达不够好。
  • @Olaf:所以,当你写“那个”时,在回应我的评论时,你指的是你的 Python 示例,而不是我链接的 C++ 示例?这至少是一个积极误导的评论。边缘不真实。

标签: c++ c global-variables


【解决方案1】:

C++ 是一种不同的编程语言。它与 C 有不同的规则。一方面,C++ 支持静态变量的非常量初始值设定项。它们在main() 之前执行。这就是代码在 C++ 中编译和工作的原因。

【讨论】:

  • 大多数编译器会在main之前执行初始化,但它是实现定义的。
  • @callyalater 所以初始化程序可能不会在main() 之前执行?你能引用那个标准吗?
  • 第 3.6.2(4) 节。我在下面的回答中引用了它。
  • @callyalater 考虑到这一点,我想说大多数变量确实在第一次使用时被初始化,因为二进制图像被延迟加载(即页面错误)。
  • 这是有道理的。似乎它可能与编译器如何进行内存访问优化有关,但这只是一个猜测。
【解决方案2】:

在您的示例中,int a 是一个具有static 存储持续时间的变量。

根据 C++ 标准,第 3.6.2 (4) 节,

非局部变量是否动态初始化static存储由实现定义 持续时间在main 的第一条语句之前完成。如果初始化被推迟到某个时间点 在main 的第一条语句之后,它应该发生在任何函数或变量的第一次 odr-use (3.2) 之前 在与要初始化的变量相同的翻译单元中定义。

根据您的编译器,a 可能会在 main 之前被初始化,或者它会在第一次在 main 中使用之前被初始化。 (大多数编译器都使用前者,因为它更容易实现。)

因此,在您的示例中,int a = foo(); 正在声明和初始化具有 static 存储持续时间的变量,这在 C++ 标准中是允许的。

【讨论】:

  • 当使用int a[foo()+10]; 而不是int a = foo();时出现错误:文件范围内不允许可变长度数组声明。我知道这就是我们需要constexpr 的原因。但是,为什么会失败呢?是具有static 存储持续时间的全局数组吗?谢谢。
  • 这有点不同,因为它将数组引入到混合中,这些数组需要在编译时有效地保持不变(尽管许多 C++ 编译器提供了额外的功能来放宽 constexpr 对数组大小的要求)。
  • C++ 中的数组在内存中是连续布局的,这意味着在编译时必须知道它的大小以保留适当的空间量。如果 foo() 根据执行返回不同的值,则无法修复内存中的数组长度,因为它可能会有所不同。编译器无法知道foo 的返回值是否有效,因此它会在编译时引发错误。 This answer 另一个问题解释了一点。
【解决方案3】:

即使在您的 foo() 声明中没有 'constexpr' 属性,C++ 也可以编译您的代码的可能原因是您尚未将 int a 声明为 constexpr。所以编译器不需要知道a的值,可以在运行时初始化。

【讨论】:

  • @Alf 感谢您的编辑。该死的自动更正。我输入了constexpr,只是没有注意到它什么时候“更正”了。 :P
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-19
  • 2016-09-15
  • 2017-10-30
  • 1970-01-01
  • 2015-07-22
  • 2011-03-04
  • 2015-01-11
相关资源
最近更新 更多