You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带自定义构造函数的非POD结构体能否安全用于std::atomic?

关于原子计数器封装的问题解答

Hey there, let's break down your questions step by step—this is a common pitfall when trying to wrap atomic variables, so let's clarify things clearly:

1. 能不能安全使用std::atomic<my_counters>?

First off, let's get the requirements for std::atomic<T> straight (even with partial C++11 support, these core rules hold):

  • The type T must be TriviallyCopyable: this means no custom copy/move constructors, assignment operators, or destructors—all those operations have to be compiler-generated. Your struct has a custom constructor, which makes it non-trivially constructible, but that's not the dealbreaker here.
  • The bigger problem is size: std::atomic<T> relies on platform-native atomic instructions, which only support specific sizes (usually 1, 2, 4, or 8 bytes). Your my_counters has 3 int members—assuming int is 4 bytes, that's 12 total bytes, which almost certainly exceeds the maximum size your platform can handle atomically. Even if your compiler let you declare std::atomic<my_counters>, it would have to fall back to a mutex-based implementation (if supported at all), which is inefficient and not what you're looking for.

2. Will counters.counter1++ be atomic?

Absolutely not. When you wrap the struct in std::atomic, the atomicity only applies to whole-object operations (like counters.load() or counters.store(...)). Directly accessing counters.counter1 and incrementing it bypasses the atomic wrapper entirely—this is equivalent to modifying a regular non-atomic int in multiple threads, which will cause data races and undefined behavior.

3. The right way to encapsulate your counters

Your goal is to group atomic counters for easier management, so keep the atomicity at the member level, not the whole struct:

struct my_counters {
    std::atomic<int> counter1;
    std::atomic<int> counter2;
    std::atomic<int> counter3;

    // Custom constructor to initialize all atomics
    my_counters(int c1, int c2, int c3) 
        : counter1(c1), counter2(c2), counter3(c3) {}
};

This approach checks all your boxes:

  • Each counter is a proper std::atomic<int>, so operations like counter1++, counter2--, and counter3 +=4 are all atomic and thread-safe.
  • You get the custom constructor you need to initialize values upfront.
  • Even with partial C++11 support, std::atomic<int> is one of the most widely implemented parts of the standard—your compiler will almost certainly handle it correctly.

A quick note on the POD confusion

Some old resources claim std::atomic<T> requires POD types, but that's a misunderstanding. The C++11 standard actually requires T to be TriviallyCopyable, not strictly POD. But even if your struct were TriviallyCopyable, the size issue would still make std::atomic<my_counters> a bad choice.

Extra tips for limited C++11 support

If your compiler is really behind (e.g., doesn't support std::atomic<int> constructors), you can fall back to platform-specific atomic APIs:

  • On Linux: Use __sync_fetch_and_add or __sync_sub_and_fetch
  • On Windows: Use InterlockedIncrement or InterlockedAdd
    But stick with std::atomic if you can—it's portable and cleaner.

内容的提问来源于stack exchange,提问作者code_fodder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:14:40