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

如何在不进行拷贝初始化的情况下通过对象指针获取原对象?

问题描述

我需要处理一个链表结构,节点通过指针互相链接,第一个节点的ptrTo指向第二个节点的this指针。现在有一个函数Interface,参数是LinkNode的引用r_node,遇到了以下问题:

  • 直接用r_node = r_node.forward()不符合预期:引用不能重新赋值,这条语句会把forward()返回的对象内容拷贝到r_node本身,而不是切换到下一个节点。
  • 不想用指针语法(比如nodeptr->xxx):因为代码里已经有几百次对象调用的语法(node.xxx),改动成本太高。
  • 不能修改forward()函数或新增成员函数,且forward()返回的是引用而非指针。
  • 拷贝对象(比如LinkNode node = r_node)会导致问题:因为链表依赖原对象的this指针,拷贝会生成新对象,破坏链表结构。
  • 普通引用(比如LinkNode& node = r_node)无法重新赋值,node = node.forward()同样只能拷贝内容,不能切换节点。

现有代码

Interface.cpp

#include "node.h"

void Interface(LinkNode& r_node){

    LinkNode* nodeptr = &r_node;
    // 我想在这里从nodeptr或r_node创建一个可切换的对象引用
    
    node=node.forward();
    
}

node.h

#pragma once
#include <string> // 补充原代码遗漏的头文件

class LinkNode{
    
    private:
        std::string payload="";
        LinkNode* ptrTo = nullptr;
        LinkNode* ptrBack = nullptr;
    
    public:
        LinkNode(std::string payload=""){ this->payload=payload; }
        ~LinkNode(){}

        LinkNode* getPtr()        { return this; }
        void setPtrTo   (LinkNode* ptr){ ptrTo = ptr; }
        void setPtrBack (LinkNode* ptr){ ptrBack = ptr; }

        LinkNode& forward()  { return *ptrTo; }
        LinkNode& backward() { return *ptrBack; }
        
};

main.cpp

#include <iostream>
#include <stdlib.h>
#include <string> // 补充原代码遗漏的头文件
#include "node.h"

void Interface(LinkNode& node);

int main(){

    int lengthofLink=0;
    std::cout<<"Submit your length of link: "<<std::endl;
    std::cin>>lengthofLink;

    LinkNode** array{ new LinkNode* [lengthofLink]{} };

    /* 确定节点数据并将指针存入数组 */
    for(int i=0;i<lengthofLink;i++){ 
        std::string data;
        std::cout<<"Enter "<<i+1<<". payload: ";
        std::cin>>data;
        array[i] = new LinkNode (data); // array[i]保存new返回的指针
    }

    for(int i=0; i<lengthofLink-1; i++){ // 正向链接
        LinkNode* t_ptr_f = array[i+1]->getPtr();
        array[i]->setPtrTo(t_ptr_f); 
    }

    for(int i=lengthofLink; i>=2 ; i--){ // 反向链接
        LinkNode* t_ptr_b = array[i-2]->getPtr();
        array[i-1]->setPtrBack(t_ptr_b);
    }

    LinkNode& r_node = *(array[0]);
    Interface(r_node);

    // 释放内存
    for(int i=0;i<lengthofLink;i++){ 
        delete array[i];
    }
    delete[] array;

    return EXIT_SUCCESS;
}

解决方案

可以使用std::reference_wrapper实现可重新绑定的引用,它既保留了对象调用的语法,又能像指针一样切换指向的节点。修改后的Interface.cpp代码如下:

#include "node.h"
#include <functional> // 必须包含此头文件以使用std::reference_wrapper

void Interface(LinkNode& r_node){

    // 用reference_wrapper包装初始节点
    std::reference_wrapper<LinkNode> node = r_node;

    // 切换到下一个节点:重新绑定reference_wrapper,无对象拷贝
    node = node.get().forward();

    // 保留类似对象的调用语法,两种写法都可行
    std::cout << "当前节点payload:" << node.get().payload << std::endl;
    std::cout << "当前节点payload:" << node->payload << std::endl;
}

关键说明

  • std::reference_wrapper<T>是可拷贝、可赋值的包装类,内部保存对象引用,通过get()可获取原始引用,也可直接用->调用成员函数(类重载了该操作符)。
  • node = node.get().forward():node.get()返回当前包装的节点引用,调用forward()得到下一个节点的引用,赋值给node即可完成节点切换,全程无对象拷贝,完全复用原链表节点。
  • 原有node.xxx的调用只需改为node->xxx或node.get().xxx,改动量极小,保留了熟悉的对象调用语法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 12:31:06