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

CppCoreGuidelines R.33为何建议传递unique_ptr引用实现指针重置?

核心语义区分

你混淆了三种完全不同的unique_ptr操作场景,对应完全不同的传参方式:

  • 修改调用方持有的unique_ptr本身的指向(也就是规则里说的reseat):用unique_ptr<T>&
  • 从调用方完全拿走unique_ptr的所有权:用传值unique_ptr<T>,调用时需移动
  • 仅读写unique_ptr指向的底层对象,不碰指针本身和所有权:直接传T*或T&即可,不需要传递unique_ptr本身

为什么reseat需要传引用

reseat的核心需求是:修改调用方栈上的那个unique_ptr对象本身,改完之后所有权仍然归调用方所有,调用方后续可以正常使用修改后的unique_ptr。
如果用传值的方式,函数拿到的是原unique_ptr的移动副本,修改的只是函数内部的局部变量,不会影响调用方的原指针,完全达不到reseat的效果。

示例:reseat场景

// 需求:替换调用方传入的unique_ptr指向的对象,所有权仍归调用方
void reset_to_new_widget(std::unique_ptr<Widget>& ptr) {
    // 直接修改调用方的unique_ptr,让它指向新构造的Widget
    ptr = std::make_unique<Widget>(/* 新的构造参数 */);
}

// 调用方代码
int main() {
    auto my_widget = std::make_unique<Widget>(100);
    std::cout << my_widget->get_value() << std::endl; // 输出100

    reset_to_new_widget(my_widget);
    std::cout << my_widget->get_value() << std::endl; // 输出新对象的值,所有权仍在main
    return 0;
}

传值的适用场景

只有当函数要完全接管unique_ptr的所有权时,才需要用传值+移动的方式,这种场景下调用方的原unique_ptr在函数调用后会变为空,不能再使用:

// 需求:接管传入的unique_ptr所有权,存入全局存储
void store_widget(std::unique_ptr<Widget> ptr) {
    global_widget_pool.push_back(std::move(ptr));
}

// 调用方代码
int main() {
    auto my_widget = std::make_unique<Widget>(100);
    store_widget(std::move(my_widget));
    // 此时my_widget已经为空,不能再访问
    return 0;
}

修改底层对象的场景

如果仅需要修改unique_ptr指向的底层对象,不需要修改指针本身的指向,也不需要变动所有权,直接传递底层对象的引用或指针即可,不需要传递unique_ptr本身:

void modify_widget(Widget& w) {
    w.set_value(200);
}

// 调用
modify_widget(*my_widget);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 22:18:04