在我们的一个项目中广泛使用的包含文件中,我们有这些方便的常量:
const double kPi = asin(1.0) * 2.0;
const double kPiHalf = asin(1.0);
const double kDeg2Rad = asin(1.0) / 90.0;
const double kRad2Deg = 90.0 / asin(1.0);
在运行时使用函数结果计算一次(精确的)常量是个坏主意吗?
我们收到的一些最近的故障转储(在 OS X 上)看起来很狡猾 - 尽管发生了崩溃,但它们有一个堆栈帧,其中包含 const double kRad2Deg
行的地址在深层在应用程序中的某个地方向上堆栈跟踪。很奇怪。
在启动阶段很早就调用数学函数是否可能搞砸事情?
我知道我们可以用常量替换函数调用,但我想大致了解问题(如果有的话)。
最佳答案
简答,使用<cmath>
.
长答案:在静态初始化器中调用函数是一个棘手的问题,因为函数本身可能依赖于静态初始化的数据并且初始化顺序未定义,所以一般,这是不好的做法.
foo.cpp
namespace {std :: vector <int> data;}
int foo (int i) {
data .push_back (i);
return data .size ();
}
酒吧.cpp
int f = foo (123);
这很危险,因为 data
可能还没有 build 。 foo.cpp 的安全版本是
namespace {
std :: vector <int> & data () {
static std :: vector <int> d;
return d;
}
}
int foo (int i) {
data () .push_back (i);
return data () .size ();
}
如果您不能保证所涉及的所有函数都遵循此模式,那么您就不安全。
另一方面,静态内置类型在任何事情发生之前都会将它们的值加载到内存中,所以它们没问题。
foo.cpp
const double pi = M_PI;
酒吧.cpp
int main () {
double foo = pi;
}
这很好。
还是用<cmath>
,标准要求其值尽可能准确。表演 90.0/asin(1.0)
只会加剧错误。
关于c++ - 将常量定义为函数会导致 header = 坏主意?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8900274/