所以我看到很多文章现在声称在C++上双重检查锁定,通常用于防止多个线程尝试初始化一个懒惰的单例,被打破了.正常双重检查锁定代码如下所示:
class singleton {
private:
singleton(); // private constructor so users must call instance()
static boost::mutex _init_mutex;
public:
static singleton & instance()
{
static singleton* instance;
if(!instance)
{
boost::mutex::scoped_lock lock(_init_mutex);
if(!instance)
instance = new singleton;
}
return *instance;
}
};
Run Code Online (Sandbox Code Playgroud)
问题显然是行分配实例 - 编译器可以自由分配对象,然后将指针分配给它,或者将指针设置为它将被分配的位置,然后分配它.后一种情况打破了这个习惯用法 - 一个线程可以分配内存并分配指针,但在它进入休眠状态之前不运行单例的构造函数 - 然后第二个线程将看到该实例不为null并尝试返回它,即使它尚未建成.
我看到了一个使用线程局部布尔值的建议并检查而不是instance.像这样的东西:
class singleton {
private:
singleton(); // private constructor so users must call instance()
static boost::mutex _init_mutex;
static boost::thread_specific_ptr<int> _sync_check;
public:
static singleton & instance()
{
static …Run Code Online (Sandbox Code Playgroud) singleton multithreading locking sequence-points double-checked-locking
我认为标题中很清楚.我对此并不完全确定,而且我无法通过谷歌找到一个好的答案(唉,我还没有致力于标准的精美艺术),所以我问:
int i = x++, j = x++;
Run Code Online (Sandbox Code Playgroud)
这个定义了吗?我很确定i = x++, j = x++;正常语句是未定义的行为是逗号运算符,它是一个序列点并且是合法的,但没有一个来源很清楚初始值设定项是以分号结束还是一旦下一个变量开始被声明,因为那不是逗号运算符,我找不到明确的答案.所以要么a)逗号结束初始化器,是一个序列点,这是有效的,或者b)它没有.这是什么?
为了排除,我知道我应该简化头痛并将其写成:
int i = x++;
int j = x++;
Run Code Online (Sandbox Code Playgroud)
并保证它已定义.我出于好奇而要求更多.
为什么以下给定的表达式会调用未定义的行为?
int i = 5;
i = (i,i++,i) + 1
Run Code Online (Sandbox Code Playgroud)
我的问题在这里受到Als问题的影响
是否有保证的以下java代码的执行顺序:
int i = getA() + getB();
Run Code Online (Sandbox Code Playgroud)
是getA()之前一直执行的getB(),因为任何一般人所期望的?
对于这个非变量的例子:
int Func1();
double Func2();
void MyFunc( int, double );
int main()
{
MyFunc( Func1(), Func2() );
//...
}
Run Code Online (Sandbox Code Playgroud)
它没有规定是否Func1()还是Func2()先计算,只是两者都必须做之前MyFunc()被调用.
这个测序如何与可变参数的扩展一起工作?
template < typename Func, typename ...Args >
void MyFunc2( Func &&f, Args&& ...a )
{
int b[] = { f( std::forward<Args>(a) )... };
//...
}
Run Code Online (Sandbox Code Playgroud)
假设这f是一个在第一次调用后改变其状态的函数对象.是否会f为每个段调用a?换句话说,将f在a列表中的第一个项目,然后第二个项目,第三个项目等上调用,而不是随机跳过扩展列表?我们曾经在每个项目之间调用序列点吗?
c++ variadic-functions sequence-points variadic-templates c++11
本着与序列点相关的未定义行为的精神,例如"x = ++ x",它是否真的未定义?,如何让编译器抱怨这样的代码?
具体来说,我使用的是Visual Studio 2010和Xcode 4.3.1,后者是OSX应用程序,并没有提醒我这一点.我甚至把VS2010上的警告发送到"全部",并且很高兴编译了这个.(为了记录,VS2010的版本在变量中添加了1,其中Xcode的版本保持变量不变.)
c visual-studio-2010 undefined-behavior sequence-points xcode4.3
如果i是一个int,则像这样的表达式++i + ++i是未定义的行为,因为有 2 个无序的修改i。然而, ifi是一些int类似的类,++i + ++i而是具有不确定顺序的修改,因此是定义的行为(在这种情况下具有确定性结果)。是否存在对原语的操作不排序而不是不确定排序会更好的情况?如果是这样,为什么这种情况不适用于用户创建的类型?如果不是,为什么原始操作根本没有顺序?
以下两个代码块完全相同并实现相同的功能吗?它在运行程序时显示相同的内容,但我要感谢一些严格的解释.
for(i=1;i<=10;i++)
{
printf("%d\n",i);
}
Run Code Online (Sandbox Code Playgroud)
和
for(i=1;i<=10;printf("%d\n",i),i++);
Run Code Online (Sandbox Code Playgroud)
该for环路期望有效C语句作为参数,不是吗?但即使我已经在StackOverflow上验证了这样的语句x+=4,y=x*2;是安全的,因为这里的逗号充当了序列点,对于在上面printf("%d\n",i),i++)的for循环中作为参数传递的语句是否相同?
如果是,请费心回答由此产生的小问题:
该comma行为是否在包含许多逗号分隔的语句中作为序列点
函数调用如下:
printf("Enter number\n"),scanf("%d",&number),printf("You entered %d",number);
如何解释下面代码的输出:
include <stdio.h>
int main(void) {
int k;
printf("%d %d\n",k=1,k=3);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我的想法是1将分配给k变量然后1打印.同样3将分配给k和输出3.
预期产出
1 3
Run Code Online (Sandbox Code Playgroud)
实际产出
1 1
Run Code Online (Sandbox Code Playgroud)
我是从外推
int a;
if (a = 3) {
...
}
Run Code Online (Sandbox Code Playgroud)
等于
if (3) {
...
}
Run Code Online (Sandbox Code Playgroud)
请让我知道我哪里错了?
类似的代码例如(a+=1)%=7;,其中 a 是一个int变量。
我们知道运算符+=or=不是序列点,因此我们在两个相邻的序列点之间有两个副作用。(我们这里使用的是cpp98的序列点规则)
然而,赋值运算符喜欢+=或=保证在赋值后返回左值,这意味着执行顺序在某种程度上是“定义的”。
那么这是一种未定义的行为吗?
c++ undefined-behavior sequence-points language-lawyer c++98