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

含atomic成员的对象容器编译错误解决方法咨询

解决包含std::atomic成员的对象存储到容器的编译错误

问题根源

std::atomic从C++11开始就被设计为不可拷贝、不可移动的类型——标准库显式删除了它的拷贝构造/赋值函数,也没有提供移动操作。这是因为拷贝原子变量会破坏其核心的原子语义:原子操作的意义在于保证多线程下的状态一致性,而拷贝动作本身无法被原子化,会引发竞态条件。

你的代码里两个编译错误都源于此:

  1. std::list<S> l2 = l1:容器拷贝需要元素支持拷贝构造,但S因包含std::atomic成员,默认生成的拷贝构造被禁用。
  2. std::make_shared<S>(s1):尝试用s1拷贝构造新的S对象,同样触发禁用的拷贝构造。

解决方案

方案1:给S添加移动构造/赋值,直接存储对象

如果想直接在容器里存储S对象,可以手动实现S的移动构造和移动赋值,通过原子操作转移状态,避免拷贝:

#include <atomic>
#include <list>

struct S {
    std::atomic<int> n_{0};

    // 移动构造:用exchange原子转移原对象的值,同时重置原对象的原子变量
    S(S&& other) noexcept : n_(other.n_.exchange(0)) {}

    // 移动赋值
    S& operator=(S&& other) noexcept {
        if (this != &other) {
            n_.store(other.n_.exchange(0));
        }
        return *this;
    }

    // 保留默认构造函数
    S() = default;
};

int main() {
    std::list<S> l1;
    // 用emplace_back直接在容器内构造元素,无需拷贝/移动
    l1.emplace_back();

    // 支持移动容器(若要复制容器,需手动遍历构造新元素)
    std::list<S> l2 = std::move(l1);

    // 向容器添加元素:移动已有的S对象
    S s1;
    s1.n_.store(42);
    l2.push_back(std::move(s1)); // 移动后s1的n_会被设为0
}

方案2:存储智能指针(更简单的常用方案)

如果不需要直接存储对象本身,用std::shared_ptr或std::unique_ptr包裹S是更省心的选择——智能指针的拷贝/移动不会涉及S对象的拷贝,只是管理对象的所有权:

#include <atomic>
#include <list>
#include <memory>

struct S {
    std::atomic<int> n_{0};
};

int main() {
    std::list<std::shared_ptr<S>> l;

    // 直接构造新的S对象,无需拷贝
    auto ss1 = std::make_shared<S>();
    ss1->n_.store(42);
    l.push_back(ss1);

    // 若要基于已有S的状态创建新对象,手动原子复制值
    S s1;
    s1.n_.store(100);
    auto ss2 = std::make_shared<S>();
    ss2->n_.store(s1.n_.load()); // 原子加载s1的值到新对象
    l.push_back(ss2);
}

关键注意事项

  • 永远不要尝试绕过std::atomic的拷贝限制(比如用memcpy),这会导致未定义行为,彻底破坏原子语义。
  • 使用移动构造时,要明确移动后原对象的原子变量会被重置(示例中用exchange(0)),确保原对象处于有效状态。
  • 多线程场景下,存储智能指针的方案更易维护:智能指针负责线程安全的所有权管理,std::atomic负责对象内部状态的原子操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 05:25:20