为什么逻辑"与/或"的左操作数不携带对父求值的依赖项
Why do left operands of logical AND/OR not carry dependency to the parent evaluation?
根据C++标准:
如果-A的值用作B的操作数,则求值A对求值B具有依赖关系,除非:
--B是对std::kill_dependency(29.3(或的任何专门化的调用
--A是内置逻辑AND(&&,请参见5.14(或逻辑or(||,请参见5.15(运算符或的左操作数
--A是条件(?:,见5.16(运算符或的左操作数
--A是内置逗号(,(运算符(5.18(的左操作数;(…(
我可以理解为什么在关系之前排序的依赖关系会在kill_dependency调用时停止,但为什么逻辑AND、OR、逗号等运算符也会破坏依赖链?
这是否意味着下面的代码有未定义的行为?
//thread1
int y = 2
atomicVal.store(true);
//thread2
auto x = atomicVal.load(std::memory_order_consume);
cout << x && y;
memory_order_consume
试图公开一个用于C++的asm级CPU功能。(它暂时被弃用,直到它可以被重新设计成编译器可以在实践中实现的东西,并且在源代码中不需要太多kill_dependency
噪声(。理解CPU的行为是理解设计用来公开它的C++程序的关键
这一切都是关于数据依赖关系,而不是像条件分支那样的控制依赖关系。C++11:memory_order_relaxed和memory_order_sume之间的区别以及[[carries_dependency]]它的含义和如何实现有更多的细节。
例如,add x2, x2, x3
指令在其两个输入寄存器都准备好之前不能执行,ldr w1, [x2]
也不能在地址准备好之前执行加载,所以如果x2
来自另一个加载,它会自动在这个加载之前排序。(假设CPU硬件的设计不会违反因果关系,例如,在极少数情况下,通过进行值预测或DEC Alpha所做的任何事情来违反因果关系(。但是cbz w1, reg_was_zero
是可以预测的,所以让reg_was_zero: ldr w3, [x4]
等待产生w1的负载是不够的。(这是AArch64 asm,BTW,一种保证依赖排序的弱排序ISA。(
||
或left && right
的短路评估在逻辑上与if(left) right
相同,因此即使左侧尚未执行,分支预测+推测执行也可以预期在右侧运行没有数据依赖,只有控制依赖
很明显,逗号left, right
根本不会在两边之间建立任何连接,它基本上是将left; right;
塞进一个表达式中的一种方式。
当然,如果在左侧和右侧都使用相同的变量,则数据依赖项可以以这种方式存在,但它不是由运算符创建的。
- 如何从C++中的依赖类型中获得它所依赖的类型
- 将--whole archive链接器选项与CMake和具有其他库依赖项的库一起使用
- 将依赖名称显式标记为类型名和模板的奇怪之处
- 在 Windows 上,是否可以让 dll 在不使用 PATH 环境变量的情况下在另一个文件夹中查找依赖项?
- C++GTKMM gui循环依赖关系
- 通过ccmake在cmake中缓存依赖选项
- 当基类是依赖类型时,这是一个缺陷吗
- 从不同的附加依赖项中识别等同命名的函数
- 如何在 CMake 中对目标依赖项进行分组?
- 是否可以依赖函数范围的静态变量来执行程序关闭期间调用的方法?
- 为什么构建目录中新构建的共享库与安装目录中的副本具有不同的依赖项集?
- VS 2015 链接错误 无法构建依赖于 libcurl 的项目
- 通过依赖类型使用非类型模板参数的单类型模板参数类模板的部分专用化
- 为什么内存屏障依赖于变量?
- node-gyp 的先有鸡还是先有蛋的问题:指向依赖项中的头文件
- 反转依赖于 end() 的迭代器
- GCC,CMake,预编译标头和维护依赖项
- 使用 'typename' 关键字将非类型视为依赖上下文中的类型
- 使用 Git 处理 C++ Visual Studio 2019 解决方案的外部依赖项源代码管理的最佳方法是什么?
- 为什么依赖模板类型在部分专用化中不可推导?