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

为何结构化绑定后返回std::unique_ptr必须使用std::move?

结构化绑定std::unique_ptr时的C2280错误解析

问题场景

以下代码编译时会触发C2280错误,核心原因是编译器尝试复制std::unique_ptr:

#include <memory>

std::pair<int, std::unique_ptr<int>> CreatePair()
{
    std::unique_ptr<int> my_int(new int);
    return { 1, std::move(my_int) };
}
std::unique_ptr<int> GetUinquePtr()
{
    auto [ignore, unique_ptr] = CreatePair();
    return unique_ptr; // <- 编译错误C2280:尝试引用已删除的函数
}
int main()
{
    auto unique_ptr = GetUinquePtr();
}

完整错误信息:

error C2280: 'std::unique_ptr<int,std::default_delete<int>>::unique_ptr(const std::unique_ptr<int,std::default_delete<int>> &)': attempting to reference a deleted function

错误原因

std::unique_ptr是独占所有权的智能指针,其拷贝构造函数被显式删除,仅支持移动语义完成所有权转移。

在结构化绑定auto [ignore, unique_ptr] = CreatePair()中,声明的unique_ptr是原std::pair中对应成员的左值绑定(表现为左值)。直接return unique_ptr时,编译器会尝试调用其拷贝构造函数生成返回值,这就触发了对删除函数的引用错误。

可行写法说明

1. 显式使用std::move

添加std::move后,会将左值类型的unique_ptr转换为右值,触发其移动构造函数,符合std::unique_ptr的所有权转移设计:

std::unique_ptr<int> GetUinquePtr()
{
    auto [ignore, unique_ptr] = CreatePair();
    return std::move(unique_ptr); // <- 此写法可行
}

2. 使用std::tie

std::tie会将已声明的unique_ptr与std::pair的成员绑定,这里执行的是移动赋值操作(把CreatePair()返回的pair中的unique_ptr所有权转移到提前声明的变量中)。后续return unique_ptr时,编译器会对局部自动变量执行隐式移动(C++11及以后的规则),因此无需显式std::move:

std::unique_ptr<int> GetUinquePtr()
{
    std::unique_ptr<int> unique_ptr;
    std::tie(std::ignore, unique_ptr) = CreatePair();
    return unique_ptr; // <- 此写法可行
}

结论

是的,通过结构化绑定获取std::unique_ptr后,返回时必须显式使用std::move——因为结构化绑定的变量是左值,默认会触发拷贝操作,而std::unique_ptr禁止拷贝。这并非操作失误,而是完全符合C++中std::unique_ptr的所有权规则和结构化绑定的语义。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 11:25:17