- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
给定一个从另一个类的静态成员变量初始化的静态成员变量,非文字struct ii
有时默认初始化为0
或到333
。这取决于编译或链接顺序。 伪代码演示:
class StaticClass: // file 'ONE.cpp/.hpp'
static int i = 2
static struct ii { int a = 333 }
class ABC: // file 'abc.cpp'
static int abc_i = StaticClass::i // always 2
static struct abc_ii = StaticClass::ii // sometimes 0, sometimes 333
调用 g++ -std=c++11 abc.cpp ONE.cpp && ./a.out
结果 i = 2/ii = 0
(gcc 4.8 .1,与 clang++ 3.7 相同;-Wall -Wextra
从不提示)。
但是调用 g++ -std=c++11 ONE.cpp abc.cpp && ./a.out
导致 i = 2/ii = 333
!
ONE.o abc.o
与 abc.o ONE.o
以及以一种或另一种方式连接文件时也会发生同样的情况:
cat ONE.cpp abc.cpp > X.cpp && g++ X.cpp && ./a.out
对比cat abc.cpp ONE.cpp > Y.cpp && g++ Y.cpp && ./a.out
删除包含并在单个文件中四处移动代码,当存在此顺序时默认初始化为 0:
const OneI ABC::def_ii = StaticClass::ii; const OneI StaticClass::ii = OneI{333};
还有一个到 333 的顺序:
const OneI StaticClass::ii = OneI{333}; const OneI ABC::def_ii = StaticClass::ii;
为什么这甚至会发生在两个独立的编译单元中?可以通过始终强制执行后者排序来以某种方式避免这种情况吗?在 ABC
中使用指向 StaticClass::ii
的静态指针是否安全(不过我不想这样做)?
完整的 C++ 代码:
/* File: abc.cpp */
#include <iostream>
#include "ONE.hpp"
struct ABC {
ABC();
static const int def_i;
static const OneI def_ii;
void arg_i(const int &x) { std::cout << "i = " << x << " ";};
void arg_ii(const OneI &x) { std::cout << "/ ii = " << x.a << " ";};
};
ABC::ABC() {
arg_i(def_i);
arg_ii(def_ii);
}
const int ABC::def_i = StaticClass::i;
const OneI ABC::def_ii = StaticClass::ii;
int main() {
ABC a;
std::cout << '\n';
}
/* End: abc.cpp */
/* File: ONE.cpp */
#include <iostream>
#include "ONE.hpp"
const int StaticClass::i = 2;
const OneI StaticClass::ii = OneI{333};
/* End: ONE.cpp */
/* File: ONE.hpp */
#include <iostream>
#ifndef One
#define One
struct OneI {
OneI(int a_) : a(a_) { }
int a;
};
struct StaticClass {
const static int i;
const static OneI ii;
};
#endif // One header guard
/* End: ONE.hpp */
最佳答案
恭喜!您遇到了 static initialization order fiasco .
静态对象的初始化顺序没有跨多个翻译单元定义。
StaticClass::ii
在 ONE.cpp
中定义,ABC::def_ii
在 abc.cpp
。因此
StaticClass::ii
可能会也可能不会在 ABC::def_ii
之前初始化。由于 ABC::def_ii
的初始化使用了 StaticClass::ii
的值,因此该值将取决于 StaticClass::ii
是否已初始化†.
定义了翻译单元内的静态对象的初始化顺序。对象按照它们被定义的顺序被初始化。因此,当您连接源文件时,定义了初始化顺序。但是,当您以错误的顺序连接文件时,定义的初始化顺序是错误的:
const OneI ABC::def_ii = StaticClass::ii; // StaticClass::ii wasn't initialized yet
const OneI StaticClass::ii = OneI{333};
Can this be avoided somehow by enforcing the latter ordering all the time?
最简单的解决方案是在同一个翻译单元中以正确的顺序定义两个对象。一个更通用的解决方案是使用 Construct On First Use Idiom 初始化静态对象。 .
Is using a static pointer in ABC
to StaticClass::ii
safe (I'd prefer not to, though)?
只要在定义指向对象的另一个翻译单元中的静态对象初始化期间不使用指针的解引用值,就可以将 ABC::def_ii
替换为一个指针是安全的。
† StaticClass::ii
将在静态初始化阶段进行零初始化††。静态初始化顺序失败涉及动态初始化阶段††。
†† C++ 标准草案 [basic.start.static]
If constant initialization is not performed, a variable with static storage duration ([basic.stc.static]) or thread storage duration ([basic.stc.thread]) is zero-initialized ([dcl.init]). Together, zero-initialization and constant initialization are called static initialization; all other initialization is dynamic initialization. Static initialization shall be performed before any dynamic initialization takes place. [ Note: The dynamic initialization of non-local variables is described in [basic.start.dynamic]; that of local static variables is described in [stmt.dcl]. — end note ]
关于C++:使用int vs struct对静态成员变量进行依赖初始化的静态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40107792/
我正在尝试使用 y 组合器在 Scala 中定义 gcd: object Main { def y[A,B]( f : (A => B) => A => B ) : A => B = f(y(f)
我正在尝试了解返回指向函数的指针的函数,在我尝试编译代码后,它给了我这种错误: cannot convert int (*(int))(int) to int (*(int))(int) in ass
所以我一直在关注 youtube 上的游戏编程教程,然后弹出了这段代码:bufferedImageObject.getRGB(int, int, int, int, int[], int, int);
我正在将时间现在 与存储在数据库某处的时间进行比较。数据库中存储的时间格式为“yyyyMMddHHmmss”。例如,数据库可能会为存储的时间值返回 201106203354。然后我使用一个函数将时间现
例如 Maze0.bmp (0,0) (319,239) 65 120 Maze0.bmp (0,0) (319,239) 65 120 (254,243,90) Maze0.bmp (0,0) (
评论 Steve Yegge的post关于 server-side Javascript开始讨论语言中类型系统的优点和这个 comment描述: ... examples from H-M style
我正在研究 C 的指针,从 Deitel 的书中我不明白 int(*function)(int,int) 和 int*function(int, int) 表示函数时。 最佳答案 C 中读取类型的经验
您好,我使用 weblogic 11g 创建 war 应用程序,我对 joda time 的方法有疑问 new DateTime(int, int, int, int, int, int); 这抛出了
Create a method called average that calculates the average of the numbers passed as parameters. The
var a11: Int = 0 var a12: Int = 0 var a21: Int = 0 var a22: Int = 0 var valueDeterminant = a11 * a12
我正在为一个项目设置 LED 阵列。我得到了一个 LED 阵列,可以根据引脚变化电压进行更改,但我无法添加更多引脚。 当我尝试时,编译失败并显示错误:函数“int getMode(int, int,
除了创建对列表执行简单操作的函数之外,我对 haskell 还是很陌生。我想创建一个列表,其中包含 Int 类型的内容, 和 Int -> Int -> Int 类型的函数. 这是我尝试过的: dat
这个问题已经有答案了: Java add buttons dynamically as an array [duplicate] (4 个回答) 已关闭 7 年前。 StackOverFlow问题今天
我有几个 EditText View ,我想在其中设置左侧的图像,而 setCompoundDrawablesWithIntrinsicBounds 似乎不起作用。图形似乎没有改变。 有人知道为什么会
#include using namespace std; int main() { static_assert(is_constructible, int(*)(int,int)>::val
fun sum(a: Int, b: Int) = a + b val x = 1.to(2) 我在找: sum.tupled(x),或者 sum(*x) 当然,以上都不能用 Kotlin 1.1.3
有一个函数: func (first: Int) -> Int -> Bool -> String { return ? } 返回值怎么写?我对上面 func 的返回类型感到很困惑。 最
type foo = A of int * int | B of (int * int) int * int 和 (int * int) 有什么区别?我看到的唯一区别在于模式匹配: let test_
我正在尝试制作一个 slider 游戏。在这个类中,我使用 Graphics 对象 g2 的 drawImage 方法来显示“拼图”的 block 。但在绘制类方法中,我收到此错误:找不到符号方法dr
我试着理解这个表达: static Func isOdd = i => (i & 1) == 1; 但是这是什么意思呢? 例如我有 i = 3。然后 (3 & 1) == 1 或 i = 4。然后
我是一名优秀的程序员,十分优秀!