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

含std::map<unique_ptr>的Singleton类编译报错,请求排查原因

C++代码编译错误排查与修复

错误原因

  1. PersonContainer类拷贝/移动操作禁用错误:类中声明禁用拷贝/移动构造函数时,错误地将参数类型写成了Person,而非PersonContainer。这导致编译器自动生成了默认的拷贝构造函数,而默认拷贝构造会尝试拷贝成员变量m_person_map。
  2. 单例实例被错误拷贝:main函数中auto handle = PersonContainer::getInstance();语句试图拷贝单例实例(getInstance返回引用,auto推导为值类型),触发了默认拷贝构造函数的调用。而std::map中存储的std::unique_ptr不支持拷贝操作,最终导致编译失败。

修复方案

  • 修正PersonContainer类中禁用拷贝/移动操作的函数参数类型,替换为正确的PersonContainer类型。
  • 将main中的auto handle改为auto& handle,以引用方式持有单例实例,避免拷贝。
  • 补充缺失的<string>头文件,确保std::string正常编译。

修复后的完整代码

/* --------------------------------------------------------------- */
/* 头文件包含 */
#include <iostream>
#include <map>
#include <memory>
#include <string>
/* --------------------------------------------------------------- */

/* 前向声明 */
class Person;
/* --------------------------------------------------------------- */

/* 类型别名定义 */
using PersonUptr = std::unique_ptr<Person>;
/* --------------------------------------------------------------- */

/** @brief 用于存储记录的Person类 */
class Person {
public:
    /** @brief 显式构造函数 */
    explicit Person(const std::string& name)
                : m_name(name) {}

    /** @brief Person实例必须唯一,禁用拷贝/移动 */
    Person(const Person&) = delete;
    Person(Person&&) = delete;
    Person& operator=(const Person&) = delete;
    Person& operator=(Person&&) = delete;

    /** @brief 虚析构函数 */
    virtual ~Person() =  default;

    /** @brief 返回名称/键值 */
    const std::string& getName(void) const {
        return m_name;
    }
private:
    /** @brief 类成员变量 */
    std::string m_name = "";
};

/** @brief 用于存储Person实例的单例容器类 */
class PersonContainer {
public:
    /** @brief 虚析构函数 */
    virtual ~PersonContainer() = default;

    /** @brief 禁用拷贝/移动 - 修正参数类型 */
    PersonContainer(const PersonContainer&) = delete;
    PersonContainer(PersonContainer&&) = delete;
    PersonContainer& operator=(const PersonContainer&) = delete;
    PersonContainer& operator=(PersonContainer&&) = delete;

    /** @brief 获取单例实例 */
    static PersonContainer& getInstance(void) {
        static PersonContainer container;
        return container;
    }

    /** @brief 向map中添加Person的unique_ptr */
    void addPerson(PersonUptr&& person) {
        /** FIXME 检查重复添加 */
        m_person_map.insert({person->getName(), std::move(person)});
    }
private:
    /** @brief 单例私有构造函数 */
    PersonContainer() = default;

    /** @brief 类成员变量 */
    std::map<std::string, PersonUptr> m_person_map;
};

/** @brief 测试代码 */
int main(void) {
    /** 获取容器实例 - 使用引用避免拷贝 */
    auto& handle = PersonContainer::getInstance();
    return 0;
}

错误信息翻译

从personal-record.cc:4包含的文件中:
从/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/iostream:43包含的文件中:
从/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/ios:222包含的文件中:
从/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__locale:15包含的文件中:
从/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__memory/shared_ptr.h:22包含的文件中:
从/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__memory/allocation_guard.h:15包含的文件中:
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__memory/allocator_traits.h:304:9: 错误:找不到匹配的‘construct_at’调用函数
        _VSTD::construct_at(__p, _VSTD::forward<_Args>(__args)...);
        ^~~~~~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__config:897:17: 注意:宏‘_VSTD’展开为‘std’
#  define _VSTD std
                ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__tree:2144:20: 注意:实例化函数模板特化‘std::allocator_traits<std::allocator<std::__tree_node<std::__value_type<std::string, std::unique_ptr<Person>>, void *>>>::construct<std::pair<const std::string, std::unique_ptr<Person>>, const std::pair<const std::string, std::unique_ptr<Person>> &, void, void>’时请求
    __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), _VSTD::forward<_Args>(__args)...);
                   ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__tree:2127:29: 注意:实例化函数模板特化‘std::__tree<std::__value_type<std::string, std::unique_ptr<Person>>, std::__map_value_compare<std::string, std::__value_type<std::string, std::unique_ptr<Person>>, std::less<std::string>>, std::allocator<std::__value_type<std::string, std::unique_ptr<Person>>>>::__construct_node<const std::pair<const std::string, std::unique_ptr<Person>> &>’时请求
        __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
                            ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__tree:1274:16: 注意:实例化函数模板特化‘std::__tree<std::__value_type<std::string, std::unique_ptr<Person>>, std::__map_value_compare<std::string, std::__value_type<std::string, std::unique_ptr<Person>>, std::less<std::string>>, std::allocator<std::__value_type<std::string, std::unique_ptr<Person>>>>::__emplace_hint_unique_key_args<std::string, const std::pair<const std::string, std::unique_ptr<Person>> &>’时请求
        return __emplace_hint_unique_key_args(__p, _NodeTypes::__get_key(__v), __v).first;
               ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/map:1318:29: 注意:实例化成员函数‘std::__tree<std::__value_type<std::string, std::unique_ptr<Person>>, std::__map_value_compare<std::string, std::__value_type<std::string, std::unique_ptr<Person>>, std::less<std::string>>, std::allocator<std::__value_type<std::string, std::unique_ptr<Person>>>>::__insert_unique’时请求
            {return __tree_.__insert_unique(__p.__i_, __v);}
                            ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/map:1339:17: 注意:实例化成员函数‘std::map<std::string, std::unique_ptr<Person>>::insert’时请求
                insert(__e.__i_, *__f);
                ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/map:1147:13: 注意:实例化函数模板特化‘std::map<std::string, std::unique_ptr<Person>>::insert<std::__map_const_iterator<std::__tree_const_iterator<std::__value_type<std::string, std::unique_ptr<Person>>, std::__tree_node<std::__value_type<std::string, std::unique_ptr<Person>>, void *> *, long>>>’时请求
            insert(__m.begin(), __m.end());
            ^
personal-record.cc:43:7: 注意:实例化成员函数‘std::map<std::string, std::unique_ptr<Person>>::map’时请求
class PersonContainer {
      ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__memory/construct_at.h:39:38: 注意:候选模板被忽略:替换失败[with _Tp = std::pair<const std::string, std::unique_ptr<Person>>, _Args = <const std::pair<const std::string, std::unique_ptr<Person>> &>]:调用了被隐式删除的‘std::pair<const std::string, std::unique_ptr<Person>>’拷贝构造函数
_LIBCPP_HIDE_FROM_ABI constexpr _Tp* construct_at(_Tp* __location, _Args&&... __args) {
                                     ^
生成1个错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 19:54:50