分享

c++ 连续的 std::cout<< xxx <<... 能不能保证是原子的?

 半佛肉夹馍 2023-10-20 发布于河南

不能。

C++的<<其实是函数调用的语法糖,它实际上等于调用了ostream.operator<<()。

普通的函数是无法链式调用的,因此C++强制要求ostream.operator<<返回另一个ostream。换句话说<<的函数原型是:

ostream ostream.operator<<(std::string s);

它的执行过程其实是:

ostream tempStream;

tempStream = std::cout.operator<<(a);

tempStream = tempStream.operator<<(b);

tempStream = tempStream.operator<<(c);

tempStream = tempStream.operator<<('\n');

这显然不可能是原子的。


大致看了下std::osyncstream的文档:

从文档描述看,它可能使用了scope_guard的实现思路。

也就是说,它的每次<<调用仍然不是原子的;但数据会在内部缓存、不会真的写出去。直到局部变量作用域结束、临时对象被销毁时,才会一次性的、原子的把之前缓存的信息写出去。

这在效果上,可以确保字符输出是原子的;但另一方面,如果用这个做日志的话,尤其是具名变量方式使用,它会导致日志延迟输出(不出作用域不会写盘)。这在一些要求严格的日志应用场景是不可接受的(比如银行之类、要求每个步骤严格落实到磁盘)。

而临时变量方式会好得多。因为它会在不再使用时第一时间被析构。

换句话说,它会在这行代码的分号处析构:

std::osyncstream(std::cout) << "Hello, " << "World!" << '\n';

这个行为显然更符合预期。

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多