C++ attribute: carries_dependency (since C++11) (removed in C++26)
From cppreference.net
<
cpp
|
language
|
attributes
C++
C++ language
| General topics | ||||||||||||||||
| Flow control | ||||||||||||||||
| Conditional execution statements | ||||||||||||||||
| Iteration statements (loops) | ||||||||||||||||
|
||||||||||||||||
| Jump statements | ||||||||||||||||
| Functions | ||||||||||||||||
| Function declaration | ||||||||||||||||
| Lambda function expression | ||||||||||||||||
inline
specifier
|
||||||||||||||||
| Dynamic exception specifications ( until C++17* ) | ||||||||||||||||
noexcept
specifier
(C++11)
|
||||||||||||||||
| Exceptions | ||||||||||||||||
| Namespaces | ||||||||||||||||
| Types | ||||||||||||||||
| Specifiers | ||||||||||||||||
|
||||||||||||||||
| Storage duration specifiers | ||||||||||||||||
| Initialization | ||||||||||||||||
| Expressions | ||||||||||||||||
| Alternative representations | ||||||||||||||||
| Literals | ||||||||||||||||
| Boolean - Integer - Floating-point | ||||||||||||||||
| Character - String - nullptr (C++11) | ||||||||||||||||
| User-defined (C++11) | ||||||||||||||||
| Utilities | ||||||||||||||||
| Attributes (C++11) | ||||||||||||||||
| Types | ||||||||||||||||
typedef
declaration
|
||||||||||||||||
| Type alias declaration (C++11) | ||||||||||||||||
| Casts | ||||||||||||||||
| Memory allocation | ||||||||||||||||
| Classes | ||||||||||||||||
| Class-specific function properties | ||||||||||||||||
|
||||||||||||||||
| Special member functions | ||||||||||||||||
|
||||||||||||||||
| Templates | ||||||||||||||||
| Miscellaneous | ||||||||||||||||
Declarations
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Attributes
|
(C++23)
|
||||
|
carries_dependency
(C++11)
(until C++26)
|
||||
|
(C++14)
|
||||
|
(C++17)
|
||||
|
(C++26)
|
||||
|
(C++20)
|
||||
|
(C++17)
|
||||
|
(C++17)
|
||||
|
(C++11)
|
||||
|
(C++20)
|
||||
|
(TM TS)
|
||||
|
(C++20)
|
表示释放-消费序中的依赖链 std::memory_order 会在函数内外传递,这使得编译器能够跳过不必要的内存屏障指令。
目录 |
语法
[
[
carries_dependency
]
]
|
|||||||||
说明
此属性可能出现在两种情况下:
1)
它可应用于函数或lambda表达式的参数声明,此时表明该参数的初始化会将依赖关系带入该对象的左值到右值转换。
2)
该属性可应用于函数声明的整体,此时它表示返回值携带对函数调用表达式求值的依赖关系。
此属性必须出现在任何翻译单元中函数或其参数的首次声明处。若在另一翻译单元的该函数或其参数的首次声明中未使用此属性,则程序格式错误;无需诊断。
示例
几乎未作修改地改编自 Stack Overflow 。
运行此代码
#include <atomic> #include <iostream> void print(int* val) { std::cout << *val << std::endl; } void print2(int* val [[carries_dependency]]) { std::cout << *val << std::endl; } int main() { int x{42}; std::atomic<int*> p = &x; int* local = p.load(std::memory_order_consume); if (local) { // 依赖关系是显式的,因此编译器知道 local 被解引用,并且必须确保依赖链 // 被保留以避免在某些架构上插入内存屏障。 std::cout << *local << std::endl; } if (local) { // print 函数的定义是不透明的(假设它未被内联),因此编译器必须插入内存屏障 // 以确保在 print 中读取 *p 能返回正确的值。 print(local); } if (local) { // 编译器可以假设尽管 print2 也是不透明的,但参数到解引用值的依赖关系 // 在指令流中被保留,因此不需要插入内存屏障(在某些架构上)。 // 显然,print2 的定义必须实际保留此依赖关系,因此该属性也会影响 // print2 生成的代码。 print2(local); } }
可能的输出:
42 42 42
参考文献
- C++23 标准 (ISO/IEC 14882:2024):
-
- 9.12.4 携带依赖属性 [dcl.attr.depend]
- C++20 标准 (ISO/IEC 14882:2020):
-
- 9.12.3 携带依赖属性 [dcl.attr.depend]
- C++17 标准 (ISO/IEC 14882:2017):
-
- 10.6.3 携带依赖属性 [dcl.attr.depend]
- C++14 标准 (ISO/IEC 14882:2014):
-
- 7.6.4 携带依赖属性 [dcl.attr.depend]
- C++11 标准 (ISO/IEC 14882:2011):
-
- 7.6.4 携带依赖属性 [dcl.attr.depend]
参见
|
(C++11)
(deprecated in C++26)
|
从
std::memory_order_consume
依赖树中移除指定对象
(函数模板) |