小编Leo*_*aar的帖子

num ++是'int num'的原子吗?

一般地,对于int num,num++(或++num),作为读-修改-写操作中,是不是原子.但我经常看到编译器,例如GCC,为它生成以下代码(在这里尝试):

在此输入图像描述

由于第5行对应于num++一条指令,我们可以得出结论,在这种情况下num++ 是原子的吗?

如果是这样,是否意味着如此生成num++可以在并发(多线程)场景中使用而没有任何数据争用的危险(例如,我们不需要制作它,std::atomic<int>并强加相关成本,因为它是无论如何原子)?

UPDATE

请注意,这个问题不是增量是否原子的(它不是,而且是问题的开头行).它是否可以在特定场景中,即在某些情况下是否可以利用单指令性质来避免lock前缀的开销.而且,作为公认的答案约单处理器的机器,还有部分提到这个答案,在其评论和其他人谈话解释,它可以(尽管不是C或C++).

c c++ assembly multithreading atomic

148
推荐指数
8
解决办法
1万
查看次数

为什么在2个不同的cpp文件中定义内联全局函数会产生神奇的结果?

假设我有两个.cpp文件file1.cppfile2.cpp:

// file1.cpp
#include <iostream>

inline void foo()
{
    std::cout << "f1\n";
}

void f1()
{
    foo();
}
Run Code Online (Sandbox Code Playgroud)

// file2.cpp
#include <iostream>

inline void foo()
{
   std::cout << "f2\n";
}

void f2()
{
    foo();
}
Run Code Online (Sandbox Code Playgroud)

main.cpp我已经向前宣布f1()f2():

void f1();
void f2();

int main()
{
    f1();
    f2();
}
Run Code Online (Sandbox Code Playgroud)

结果(不依赖于构建,调试/发布版本的结果相同):

f1
f1
Run Code Online (Sandbox Code Playgroud)

哇:编译器以某种方式仅选择定义file1.cpp并在其中使用它f2().这种行为的确切解释是什么?

注意,改变inlinestatic是这个问题的解决方案.将内联定义放在未命名的命名空间中也可以解决问题并且程序打印:

f1
f2
Run Code Online (Sandbox Code Playgroud)

c++ inline translation-unit

30
推荐指数
3
解决办法
3141
查看次数

我将用++ + i ++在C++ 17中评估什么?

看起来我们正在为C++获得全新的"面试问题"(我希望不是,实际上).

众所周知,在C++ 17之前,它是未定义的行为,但它是否会从C++ 17开始明确定义

由于目前似乎没有一个编译器实现了这个C++ 17修改,根据表达式评估规则,任何人都可以解释x在下面的代码中的值是什么?

int i = 0;
int x = i++ + i++;
Run Code Online (Sandbox Code Playgroud)

阿利斯代尔梅雷迪思提到这个例子在这里他CppCon 2016的谈话,但它并不完全清楚,我的最终值什么x会(虽然它似乎什么他要说的是,这将是至少1).

显然,i在这种情况下,本身将在表达式结尾处为2.

c++ operator-precedence undefined-behavior language-lawyer c++17

24
推荐指数
1
解决办法
878
查看次数

我们可以在constexpr函数中省略const局部变量吗?

例如:

constexpr int g() { return 30; }    

constexpr int f()
{
    // Can we omit const?
    const int x = g();
    const int y = 10;

    return x + y;
}
Run Code Online (Sandbox Code Playgroud)

没有必要constexpr函数中声明局部变量const

局部变量的constexpr函数不等于没有const局部变量的函数吗?const

换句话说,constexpr函数是否强加(暗示)const它的局部变量?

c++ const constexpr c++11 c++14

19
推荐指数
2
解决办法
2354
查看次数

关联性使我们具有可并行性.但是,交换性给了什么?

亚历山大·斯捷潘诺夫在A9的一篇精彩讲座(强烈推荐,顺便说一句)中指出,关联属性为我们提供了可并行性 - 这些日子是编译器,CPU和程序员自己可以利用的非常有用和重要的特性:

// expressions in parentheses can be done in parallel
// because matrix multiplication is associative
Matrix X = (A * B) * (C * D);
Run Code Online (Sandbox Code Playgroud)

但是,交换性财产给我们带来了什么?重新排序?乱序执行?

math parallel-processing cpu cpu-architecture compiler-optimization

17
推荐指数
2
解决办法
931
查看次数

为什么不允许在一个ref-qualifier上超载?

显然,不允许在ref-qualifiers上重载 - 如果删除&或者&&(只是标记,而不是它们的函数),这段代码将无法编译:

#include <iostream>

struct S {
    void f() &  { std::cout << "Lvalue" << std::endl; }
    void f() && { std::cout << "Rvalue" << std::endl; }
};

int main()
{
    S s;
    s.f();   // prints "Lvalue"
    S().f(); // prints "Rvalue"
}
Run Code Online (Sandbox Code Playgroud)

换句话说,如果您有两个具有相同名称和类型的函数,则必须定义两者,如果您定义其中任何一个.我认为这是故意的,但是原因是什么?例如,为什么不允许调用&&rvalues 的版本(如果已定义),以及f()以下变体中的其他所有内容的"primary" (反之亦然 - 尽管这会让人感到困惑):

struct S {
    void f()    { std::cout << "Lvalue" << std::endl; }
    void f() && { std::cout << "Rvalue" …
Run Code Online (Sandbox Code Playgroud)

c++ overloading rvalue language-lawyer c++11

13
推荐指数
1
解决办法
589
查看次数

是否可以将堆栈对象地址添加到新的位置?

忽视这种做法的有用性.(当然,欢迎现实生活中的例子.)

例如,以下程序输出正确的值a:

#include <iostream>

using namespace std;

int main()
{
  int a = 11111;
  int i = 30;

  int* pi = new (&i) int();

  cout << a << " " << endl;
}
Run Code Online (Sandbox Code Playgroud)

但是,新的分配是不是应该创建一些与i(正确的后续解除分配)相邻的簿记信息,在这种情况下应该破坏堆栈i

c++ stack heap-memory placement-new new-operator

7
推荐指数
1
解决办法
710
查看次数

是尝试修改const_cast-ed,但动态分配的常量对象仍然是未定义的行为?

例如:

const int* pc = new const int(3);     // note the const
      int* p  = const_cast<int*>(pc);

*p = 4; // undefined behavior?
Run Code Online (Sandbox Code Playgroud)

特别是,编译器能否优化掉分配的*pc

如果没有,修改,试图*pc通过p仍然构成未定义的行为-如果是这样,为什么呢?

c++ heap-memory const-cast compiler-optimization undefined-behavior

6
推荐指数
1
解决办法
121
查看次数

缓存线大小背后的理论和测量是什么?

高速缓存行通常为64 字节,也存在其他大小。

我非常简单的问题是:这个数字背后是否有任何理论,或者它只是背后的工程师无疑所做的大量测试和测量的结果?

不管怎样,我想知道这些是什么(理论,如果有的话,以及决定背后的各种测试)。

cpu cpu-architecture cpu-cache

6
推荐指数
1
解决办法
1484
查看次数

缓存是否具有CPU的字节序?

换句话说,L1,L2,L3等缓存是否总是反映其CPU字节顺序

或者总是将数据存储在某些特定字节序的缓存中更有意义吗?

是否有一般设计决定

cpu endianness cpu-cache

5
推荐指数
1
解决办法
153
查看次数

在析构函数中修改类成员对象是否会导致未定义的行为?

例如:

struct B { int b_; };
struct D : B
{
    ~D()
    { // D object's lifetime ends here
        d_ = 0;  // (1) undefined behavior?
        b_ = 0;  // (2) undefined behavior also?
    }
    int d_;
};
Run Code Online (Sandbox Code Playgroud)

C++标准定义,对于类型的对象D,其寿命结束析构函数时~D()呼叫开始.

我们可以解释这意味着修改析构函数内的对象,如(1)所示,会导致未定义的行为吗?

如果是这样,如果我们修改基类子对象D,如同在(2)中那样适用吗?

c++ destructor lifetime undefined-behavior language-lawyer

3
推荐指数
1
解决办法
112
查看次数

为什么'A a {};' 删除默认构造函数A :: A()时编译?

这是有问题的代码示例:

struct A {
    A() = delete;
};

int main()
{
//  A a(); // compiles, since it's a function declaration (most vexing parse)
//  A a;   // does not compile, just as expected
    A a{}; // compiles, why? The default constructor is deleted.
}
Run Code Online (Sandbox Code Playgroud)

在这里尝试使用任何可用的编译器.我尝试了几个,没有找到一个编译错误.

c++ language-lawyer uniform-initialization c++11

3
推荐指数
1
解决办法
180
查看次数

某些未定义的行为是否比其他行为更加未定义?

这就是我的意思:i++ + i++未定义,对数组的越界写入也是如此.

超出范围的数组写入的不确定性是可以理解的:它可能被利用来运行任意代码,这是您可以获得的未定义代码.让我们调用这个运行时未定义的行为.

对于i++ + i++,然而,故事似乎是不同的.假设编译器生成了一些东西.它究竟是什么未定义的.非常不确定.事实上,它是如此不确定,我们曾经听过猫可能怀孕(虽然最近 - 从CppCon 2016,我认为 - 人们开始意识到,未定义的行为毕竟不能让猫怀孕).

但是,一旦我们打开盒子,看看编译器生成了什么,并且它不是可利用的代码(注入,数据竞争等等 - 例如,编译器选择i++ + i++完全抛弃),是不是它将完全被执行 -是不是从那一点上完美定义了

换句话说,最后一种情况是我们可以称之为编译时未定义的行为.用猫来说,它类似于薛定谔的猫,在你打开盒子之前它的状态是未知(参见生成的装配),此时你会看到要执行的实际现实.(我想知道未定义的行为是否会使有毒的死猫怀孕.)

当然,未定义的行为是适用于该标准的法律术语.问题是关于现实中发生的"行为".

c++ undefined-behavior

1
推荐指数
1
解决办法
154
查看次数