假设有一个函数(可能是成员函数)
SomeType foo()
{
static SomeType var = generateVar();
return var;
}
How var
将被初始化,如果foo
会同时从多个线程中“第一次”调用吗?
- 是否保证
generateVar()
在任何情况下都只会被调用一次(当然如果使用的话)?
- 是否保证
foo
在任何场景下多次调用都会返回相同的值吗?
- 原始类型和非原始类型的行为有区别吗?
关于 C++03:
C++03 标准定义的抽象机不包含什么是 a 的正式定义thread是,如果同时访问一个对象,程序的结果应该是什么。
没有这样的概念同步原语,在不同线程中执行的操作的顺序,数据竞赛, 等等。因此,根据定义,每个多线程 C++03 程序都包含未定义的行为。
当然,在实践中,实现确实提供了记录的行为,但标准中没有任何内容指定该行为应该是什么。因此,我想说这取决于你的编译器。
答案的其余部分将重点关注 C++11,它确实定义了并发操作的语义。
关于 C++11:
是否保证generateVar()
在任何情况下都只会被调用一次(当然如果使用的话)?
不,在任何情况下都不会。
的初始化var
保证是线程安全的,所以generateVar()
不会同时输入,但如果抛出异常generateVar()
,或通过复制构造函数或移动构造函数SomeType
(if SomeType
当然是一个 UDT),那么下次执行流进入声明时将重新尝试初始化 - 这意味着generateVar()
会再次接到电话。
根据 C++11 标准第 6.7/4 段有关块作用域变量初始化的规定静态存储时间:
[...] 如果初始化通过抛出异常退出,则初始化
不完整,因此下次控制进入声明时将再次尝试。如果控制进入
变量初始化时同时声明,并发执行需等待
完成初始化。如果在变量被调用时控制递归地重新进入声明
已初始化,行为未定义。 [...]
关于你的下一个问题:
是否保证 foo 在任何情况下多次调用时都会返回相同的值?
如果它能够返回一个值(见上文),那么是的。
原始类型和非原始类型的行为有区别吗?
不,不存在,除了没有基本类型的复制构造函数或移动构造函数之类的东西,因此也不存在复制初始化导致抛出异常的风险(当然,除非generateVar()
投掷)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)