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

如何从unique_ptr的裸指针向要求unique_ptr的函数传参(不修改API)

问题描述

我在项目中拥有一个unique_ptr变量up,该变量以裸指针形式传入函数fun1。现在需要在fun1内部调用仅读取指针内容、不做修改的函数fun2,但fun2的参数为std::unique_ptr&。请问如何从裸指针向fun2传递unique_ptr?是否存在无需修改API定义的解决方案?

相关代码

#include <iomanip>
#include <iostream>
#include <memory>
#include <string>
#include <type_traits>
#include <utility>

class Res {
        std::string s;
    public:
        Res(std::string arg) : s{ std::move(arg) } {
            std::cout << "Res::Res(" << s << ");\n";
        }
        ~Res() {
            std::cout << "Res::~Res();\n";
       }
    private:
       friend std::ostream& operator<< (std::ostream& os, Res const& r) {
           return os << "Res { s = " << r.s << "; }";
       }

};

// ptr is used just to read the content of the ptr.
// No writing is done. fun2 calls another api 
// lets say api_fun that requires unique_ptr
void fun2(std::unique_ptr<Res>& uniq_ptr){
    // api_fun(uniq_ptr);
    std::cout << uniq_ptr.get() << '\n';
}

void fun1(Res* ptr){
    //std::unique_ptr<Res> tt(ptr);
    //fun2(std::move(tt));// this deletes the mem twice.
}

int main()
{
    std::unique_ptr<Res> up(new Res("Hello, world!"));
    fun1(up.get());
    // up will be used here too
}
解决方案

首先明确:std::unique_ptr的核心是独占所有权,直接用裸指针构造新的unique_ptr会触发双重释放(如你注释的代码),这是绝对禁止的。

如果不能修改fun2的API,有两种可行方案:

方案1:临时构造不接管所有权的unique_ptr

给临时unique_ptr绑定一个空删除器,让它不会释放内存,这样既能满足fun2的参数类型要求,又不会干扰原unique_ptr的所有权:

void fun1(Res* ptr){
    // 自定义空删除器,什么都不执行
    auto noop_deleter = [](Res*) {};
    std::unique_ptr<Res, decltype(noop_deleter)> temp_ptr(ptr, noop_deleter);
    fun2(temp_ptr);
}

临时对象temp_ptr在fun1结束时销毁,由于删除器是空操作,原up的内存不会被释放,后续依然可以正常使用。

方案2:修改fun1的参数类型(更推荐)

既然fun1需要调用依赖unique_ptr的fun2,直接让fun1接收std::unique_ptr<Res>&而非裸指针,从根源上避免所有权混淆:

void fun1(std::unique_ptr<Res>& up){
    fun2(up);
}

// main函数中直接传递引用
int main()
{
    std::unique_ptr<Res> up(new Res("Hello, world!"));
    fun1(up);
    // up依然可以正常使用
}

这种做法完全符合C++智能指针的设计意图,消除了裸指针带来的所有权模糊问题,代码更安全、易维护。

注意事项

绝对不要直接用裸指针构造普通unique_ptr,这会导致两个unique_ptr同时拥有同一块内存的所有权,最终触发双重释放的未定义行为,这是C++智能指针使用中的典型错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 12:45:51