在 C++ 中,有一种原子类型std::atomic<T>。该原子类型可能是无锁的,也可能不是,具体取决于类型 T 和当前平台。如果某个类型的无锁实现在类型 T 的平台上可用,那么大多数编译器都会提供无锁atomic<T>。在这种情况下,即使我想要非无锁atomic<T>我也无法拥有它。
C++ 标准决定只保留一个,std::atomic<T>而不是一std::atomic<T>加一std::lock_free<T>(部分针对特定类型实现)。这是否意味着“在任何情况下,当后者可用时,使用非无锁原子类型都会比使用无锁原子类型更好”?(主要是在性能方面而不是易用性方面)。
与基本类型 \xe2\x80\x93和\xe2\x80\x93 不同float, C++23 中引入的新类型将始终是 IEEE 标准二进制浮点类型吗?doublelong doublefloatN_t<stdfloat>
固定宽度浮点的 cppreference 页面确实提到了精度和指数位,这与 IEEE 标准相匹配。但该页面并未在任何地方明确提及 IEEE 标准。IEEE 兼容的浮点意味着,它们不仅应该具有相同的精度和指数位,而且该标准还列出了必须以符合标准的方式支持的许多操作。那么这些类型是否严格遵循这一点呢?
\n我读过std::memory_orderC++ 并部分理解。但我对此仍然存有一些疑问。
std::memory_order_acquire说,在此加载之前,当前线程中的任何读取或写入都不能重新排序。这是否意味着编译器和 CPU 不允许移动语句下方acquire或上方的任何指令?auto y = x.load(std::memory_order_acquire);
z = a; // is it leagal to execute loading of shared `b` above acquire? (I feel no)
b = 2; // is it leagal to execute storing of shared `a` above acquire? (I feel yes)
Run Code Online (Sandbox Code Playgroud)
我可以推理出为什么在 之前执行加载是非法的acquire。但为什么这对商店来说是非法的呢?
atomic对象中无用的加载或存储是否违法?因为它们不是volatile,而且据我所知,只有 volatile 有这个要求。auto y = x.load(std::memory_order_acquire); // `y` is never used
return;
Run Code Online (Sandbox Code Playgroud)
relaxed即使使用内存顺序,这种优化也不会发生。
acquire或下方的指令?z …Run Code Online (Sandbox Code Playgroud) c++ atomic compiler-optimization memory-barriers instruction-reordering
每当我执行 C 程序时,都会有 3 个标准文件,stdin, stdout, stderr. 这些在 Linux 中映射到/proc/self/fd/0, /proc/self/fd/1, /proc/self/fd/2,它链接到/dev/pts/0我的电脑。这是伪终端,该进程向其输出并从中获取输入。
Windows 中与此等效的是什么?当我在 Windows 中执行相同的程序时,这些stdin, stdout,指向哪里?stderr
这是取自kotlin 官网的值类的精确代码片段。
interface I
@JvmInline
value class Foo(val i: Int) : I
fun asInline(f: Foo) {}
fun <T> asGeneric(x: T) {}
fun asInterface(i: I) {}
fun asNullable(i: Foo?) {}
fun <T> id(x: T): T = x
fun main() {
val f = Foo(42)
asInline(f) // unboxed: used as Foo itself
asGeneric(f) // boxed: used as generic type T
asInterface(f) // boxed: used as type I
asNullable(f) // boxed: used as Foo?, which is different from Foo
// below, …Run Code Online (Sandbox Code Playgroud) 我正在阅读有关 C++ 中的内存顺序的内容。我可以很好地理解放松和获取-释放模型。但我正在努力解决顺序一致性问题。
如果我没记错的话,从cppreference来看,std::memory_order_seq_cst“操作”相当于:
std::memory_order_seq_cst但‘栅栏’又是怎样的情况呢?它相当于其中的哪一个?
如果和上面其中之一是等价的,那另外两个呢?
据我所知,如果是情况 1(获取栅栏),编译器可以自由地将任何写操作从栅栏上方移动到栅栏下方。类似地,如果是情况 2(释放栅栏),编译器可以自由地将任何读取操作从栅栏下方移动到栅栏上方。最后,如果是情况 3(acq-rel 栅栏),则不允许编译器跨栅栏移动任何指令。它是否正确?
我仍然很困惑。以上说法可能不正确。有不对的地方请指正。
Kotlin 协程是该语言的关键功能之一。我很好奇他们是如何实现的。所以我写了这个 kotlin 代码片段,
CoroutineScope(Dispatchers.IO).launch {
someFun(6) // A suspend fun with single int argument.
} // Which is converted into a synthetic method with an extra argument of continuation type added at the end.
Run Code Online (Sandbox Code Playgroud)
然后将其编译为字节码,然后将其反编译为Java(在Android Studio中)。我懂了,
BuildersKt.launch$default(CoroutineScopeKt.CoroutineScope((CoroutineContext)Dispatchers.getIO()), (CoroutineContext)null, (CoroutineStart)null, (Function2)(new Function2((Continuation)null) {
private CoroutineScope p$;
Object L$0;
int label;
@Nullable
public final Object invokeSuspend(@NotNull Object $result) {
Object var3 = IntrinsicsKt.getCOROUTINE_SUSPENDED();
CoroutineScope $this$launch;
switch(this.label) {
case 0:
ResultKt.throwOnFailure($result);
$this$launch = this.p$;
MainActivity var10000 = MainActivity.this;
this.L$0 = $this$launch;
this.label …Run Code Online (Sandbox Code Playgroud) 下面是用于跨线程数据同步的获取-释放语义的简单示例。
// thread 1 // thread 2
data = 100;
flag.store(true, std::memory_order_release);
while(!flag.load(std::memory_order_acquire));
assert(data == 100);
Run Code Online (Sandbox Code Playgroud)
据我了解,这准确地表明了获取-释放内存顺序的使用,并且程序将按预期工作。
但如果我使用独立屏障会怎样?
// thread 1 // thread 2
data = 100;
std::atomic_thread_fence(std::memory_order_release);
flag.store(true, std::memory_order_relaxed);
while(!flag.load(std::memory_order_relaxed))
std::atomic_thread_fence(std::memory_order_acquire);
assert(data == 100);
Run Code Online (Sandbox Code Playgroud)
我一直认为这与第一个例子完全相同。
但今天我在 CppCon 上观看了 Herb Sutter 的演讲(C++ and Beyond 2012:Herb Sutter - 原子武器)。在视频中的1:07:10 ,他举了一个例子来说明独立围栏的效果并不理想。看完后我很困惑。
例子是这样的:
// thread 1 // thread 2
widget *temp = new widget();
XX mb(); XXXXXXXXXXXXXXXXXXXXX // a
global = temp;
temp2 = global;
XX mb(); XXXXXXXXXXXXXXXXXXXXX …Run Code Online (Sandbox Code Playgroud) C++ 中无前缀字符串的编码是什么?例如,所有字符串文字在 Java 中都被解析并存储为 UTF-16,在 Python3 中则被解析为 UTF-8。我猜想 C++ 文字就是这种情况u8""。但我不清楚像 之类的普通文字""。
以下代码的输出应该是什么?
#include <iostream>
#include <iomanip>
int main() {
auto c = "Hello, World!";
while(*c) {
std::cout << std::hex << (unsigned int){*c++} << " ";
}
}
Run Code Online (Sandbox Code Playgroud)
当我在我的机器上运行它时,它会给出以下输出:
48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 21
Run Code Online (Sandbox Code Playgroud)
但这有保证吗?字符串文字的 Cppreference 页面表示普通字符串文字中的字符来自翻译字符集,翻译字符集指出:
翻译字符集由以下元素组成:
- 由 ISO/IEC 10646 命名的每个字符,由其唯一的 UCS 标量值标识,以及
- 每个 UCS 标量值的不同字符,其中未分配命名字符。
从这个定义来看,翻译字符集似乎是指 Unicode(或其超集)。那么除了显性之外,""和之间没有区别吗?u8""
假设如果我希望我的字符串采用 EBCDIC 编码(只是作为练习),那么在 …
inline在说明符的 cppreference 页面上,它说:
inline当在函数的decl-specifier-seq中使用说明符时,该说明符将该函数声明为内联函数。
内联函数具有以下属性:程序中
可以有多个内联函数的定义,只要每个定义出现在不同的翻译单元中并且所有定义都相同。
...
然后,稍微低一点,它说,
该关键字的最初目的
inline是向优化器指示函数的内联替换优于函数调用。...
除了这一行之外,没有任何关于 的使用的参考inline。后一个含义inline在 C++ 标准中仍然有效吗?或者后一种形式是否比前一种形式被弃用?
如果后一种形式仍然有效,是否值得在现代编译器中使用它?我听说,即使是编译器做出内联决定,但使用inline关键字会稍微推动它。这是真的?对于这种情况,我应该inline在程序中使用关键字吗?