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

使用pmr与默认构造函数时vector::emplace_back()参数异常的原因与解决

PMR Vector emplace_back默认初始化对象时编译报错

尝试向PMR vector中emplace_back一个默认初始化的profile类对象,由于vector已用分配器初始化,容器会尝试为元素构造函数传入自身的分配器参数,但此时出现额外参数,导致编译报错。

示例代码

#include <memory_resource>
#include <cstdio>

struct profile
{
    using allocator_type = std::pmr::polymorphic_allocator<std::byte>;

    profile(allocator_type allocator = {}) {}
};

struct update
{
    using allocator_type = std::pmr::polymorphic_allocator<std::byte>;

    update(allocator_type allocator = {})
        :   profiles_( allocator )
    {
        
    }

    std::pmr::vector<profile> profiles_;
};


int main() {
    update u;

    u.profiles_.emplace_back();
}

关键错误片段

stl_construct.h: In substitution of 'template<class _Tp, class ... _Args> constexpr decltype (::new(void*(0)) _Tp) std::construct_at(_Tp*, _Args&& ...) [with _Tp = profile; _Args = {profile, const std::pmr::polymorphic_allocator<profile>&}]':

原因分析

  • PMR容器(比如std::pmr::vector)在构造元素时,会自动尝试将自身的分配器传递给元素的构造函数,这是PMR容器的特性。
  • profile类定义的allocator_type是std::pmr::polymorphic_allocator<std::byte>,但std::pmr::vector<profile>使用的分配器是std::pmr::polymorphic_allocator<profile>(PMR容器会自动将分配器的value_type转换为元素类型)。
  • 调用emplace_back()时,编译器尝试将vector的分配器转换为profile的allocator_type,但错误地触发了意外的构造匹配:把默认构造的临时profile对象和转换后的分配器一起作为参数传入,导致profile的构造函数收到两个参数,超出了定义的重载范围。

解决方法

方法1:统一分配器的value_type

将profile的allocator_type改为和vector一致的std::pmr::polymorphic_allocator<profile>,让容器传递的分配器直接匹配构造函数参数,避免类型转换带来的错误:

#include <memory_resource>
#include <cstdio>

struct profile
{
    using allocator_type = std::pmr::polymorphic_allocator<profile>;

    profile(allocator_type allocator = {}) {}
};

struct update
{
    using allocator_type = std::pmr::polymorphic_allocator<std::byte>;

    update(allocator_type allocator = {})
        : profiles_(allocator)
    {
    }

    std::pmr::vector<profile> profiles_;
};

int main() {
    update u;
    u.profiles_.emplace_back();
}

方法2:显式避免容器自动注入分配器

调用push_back({})代替emplace_back(),或者使用std::piecewise_construct显式指定空参数列表,阻止容器自动传入分配器:

// 修改main函数中的调用
int main() {
    update u;
    u.profiles_.push_back({}); 
    // 或者使用piecewise_construct:
    // u.profiles_.emplace_back(std::piecewise_construct, std::tuple<>{}, std::tuple<>{});
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 22:50:38