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

C++如何在函数内让指针指向另一个指针?是否必须拷贝?

问题解答:让函数修改外部指针的指向

咱先直接给结论:完全可以实现让test()执行后,main里的b指向a的对象,根本不需要创建对象拷贝!你的代码没生效,是因为踩了C++「值传递」的常见坑——指针本身也是按值传递的,你传给test的b是个副本,函数里修改的只是这个副本的指向,完全影响不到main里原有的b指针。

原代码问题拆解

先把你的示例代码补全并格式化,方便看清楚:

#include <iostream>
using namespace std;

class Object {}; // 原代码未定义该类,补充完整

void test(Object* a, Object* b) { 
    std::cout << "test a: " << a << std::endl; 
    std::cout << "test b: " << b << std::endl; 
    b = a; // 此处修改的是函数内部的b副本,与main中的b无关
    std::cout << "test b assigned: " << b << std::endl; 
} 

int main() { 
    Object* a = new Object(); 
    Object* b = nullptr; 
    test(a, b); 
    std::cout << "a: " << a << std::endl; 
    std::cout << "b: " << b << std::endl; // 因此这里b仍为nullptr
    delete a; 
    delete b; // 此处delete nullptr虽无错误,但无实际意义
}

输出和你给出的一致:

test a: 0x1aa8930 
test b: 0 
test b assigned: 0x1aa8930 
a: 0x1aa8930 
b: 0 

简单来说,test里的b是main中b的“替身”,你修改替身的指向,真身完全不会有变化。

三种可行的解决办法

1. 传递指针的指针(Object**)

要修改外部指针本身,就得把指针的地址传进去——相当于告诉函数“我的指针在这,你直接改它”:

void test(Object* a, Object** b) { 
    std::cout << "test a: " << a << std::endl; 
    std::cout << "test b的地址: " << b << std::endl; 
    std::cout << "test 原b的当前值: " << *b << std::endl;
    *b = a; // 通过地址直接修改原指针的指向
    std::cout << "test 修改后的原b值: " << *b << std::endl; 
} 

int main() { 
    Object* a = new Object(); 
    Object* b = nullptr; 
    test(a, &b); // 用&取b的地址传递给函数
    std::cout << "a: " << a << std::endl; 
    std::cout << "b: " << b << std::endl; // 此时b与a指向同一对象
    delete a; 
    // 注意!此处不可再delete b,a和b指向同一块内存,重复释放会导致未定义行为
}

2. 传递指针的引用(Object*&)

C++的引用是原变量的“别名”,传递指针的引用后,函数里对引用的修改会直接作用于原指针,写法比指针的指针更简洁:

void test(Object* a, Object*& b) { // 这里b是指针的引用
    std::cout << "test a: " << a << std::endl; 
    std::cout << "test b: " << b << std::endl; 
    b = a; // 直接修改原指针的指向,无需操作地址
    std::cout << "test b assigned: " << b << std::endl; 
} 

int main() { 
    Object* a = new Object(); 
    Object* b = nullptr; 
    test(a, b); // 直接传b即可,引用会自动绑定原变量
    std::cout << "a: " << a << std::endl; 
    std::cout << "b: " << b << std::endl; 
    delete a; 
    // 同样不可重复delete b
}

这是C++中更推荐的写法,代码更干净,逻辑也更清晰。

3. 让函数返回指针

如果逻辑简单,也可以让test直接返回目标地址,再在main中赋值给b:

Object* test(Object* a) { 
    std::cout << "test a: " << a << std::endl; 
    return a; // 返回a的地址
} 

int main() { 
    Object* a = new Object(); 
    Object* b = nullptr; 
    b = test(a); // 将返回值直接赋值给b
    std::cout << "a: " << a << std::endl; 
    std::cout << "b: " << b << std::endl; 
    delete a; 
}

这个方案最直观,适合不需要在函数内执行复杂操作的场景。

额外提醒

  • 当a和b指向同一对象时,绝对不能重复调用delete,这会导致内存重复释放,触发程序崩溃等未定义行为。
  • 如果你的场景需要多个指针共享对象所有权,建议使用C++智能指针(如std::shared_ptr),它能自动管理内存,避免手动delete的麻烦,也能规避这类问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:12:35