当传递链表的引用而不是指针时,如何为链表分配内存

How do you allocate memory for an linked list when passing its reference instead of its pointer?

本文关键字:链表 内存 分配 指针 引用      更新时间:2023-10-16

当传递链接列表的引用而不是指针时,如何为其分配内存?

例如:

struct node {
  string info;
  node *next;
};
void add(node &aNode){

//if I use
node *newNode;
newNode = new node;
aNode.next = newNode; //aNode.next = newNode; doesn't work either
//allocating on heap seems to give segmentation error.

}

int main() {                                                        
  node *aNode;
  aNode = new node;
  add (aNode);

}
Compiler error: error: invalid initialization of reference of type ‘node&’ from expr

或者,如果我使用

int main() {                                                        
  node aNode;
  add (aNode);
  add (aNode);
  aNode.next->next->info = "abc";
  string a = aNode.next->next->info;

}

这就造成了分割错误。

那么,是否可以仅通过引用为链表进行分配呢?(这是C++)

应该是

node * newNode = new node;
aNode.next = newNode

您必须手动删除,例如检查aNode.next是否尚未被占用(如果已被占用则删除)。

此外,add函数签名应为:

void add(node & aNode) { ... }

顺便说一句,STL附带了一个不错的<forward_list>;-)


很难说你到底在问什么,但根据问题标题,也许你脑海中有一个这样的节点结构:

struct Node {
  Node & next;
  /* payload data */
  Node(Node & n) : next(n) /* ... */ { }
};

这样一个节点将"通过引用"存储其后续节点;但您必须使用现有节点对其进行初始化!(没有所谓的"空"引用。)根据家禽椭圆形Impasse,你不能这样做。


好吧,当你继续拒绝发布你的完整代码时,这是我对你的代码的几乎字面上的复制/粘贴,对我来说很好:

更新:我正在添加一个功能,以便在末尾添加一个节点,这可能是您想要的。

#include <string>
struct node {
  std::string info;
  node *next;
  node(std::string i = "") : info(i), next(NULL) { }
};
void add(node &aNode)
{
  node *newNode;
  newNode = new node;
  aNode.next = newNode;
}
void add_at_end(node &aNode, std::string value = "")
{
  node *newNode, *n = &aNode;
  while (n->next) n = n->next; // move to the end
  newNode = new node(value);
  n->next = newNode;
}
int main()
{
  node aNode, bNode;
  add(aNode);
  add_at_end(bNode, "Hello");
  add_at_end(bNode, "World");
  add_at_end(bNode, "!");
}

g++ -o prog prog.cpp -W -Wall -pedantic编译。


最后,以下是实现相同功能的STL方法:

#include <forward_list>
#include <string>
int main() {
  std::forward_list<std::string> bList;
  bList.push_front("Hello");
  bList.push_front("World");
  bList.push_front("!");
}

main()的第二个变体中,您调用了add(aNode)两次。但你每次都为它提供相同的参数。因此,尽管您正在创建两个新的node对象,但其中一个对象将永远丢失(内存泄漏)。并且aNode.next最终指向另一个。aNode.next->next不是一个有效的指针,因此当您试图通过它访问某个内容时会出现seg错误。

根据你想要实现的目标,你可以试试这个:

node aNode;
add(aNode);        // Basically does: aNode.next = new node;
add(*aNode.next);  // Basically does: aNode.next->next = new node;

有更好的方法来创建链表,但这至少可以避免seg错误。

尝试

int main() {                                                        
  node *aNode;
  aNode = new node;
  add (*aNode);
}

您必须传递对对象的引用,而不是指针。

我检查了你的代码,在堆栈上分配时没有出现分段错误:http://ideone.com/gTRIG.


我的主张:

#include <string>
using namespace std;
struct node {
  string info;
  node *next;
  node(string str): info(str), next(NULL) {}
  ~node() { if(next != NULL) delete next; }
  node *add(string info){
    node *newNode = new node(info);
    return aNode.next = newNode;
  }
};
int main(){
  node rootNode("My rootnode");
  node *nxt = rootNode.add("Next node");
  nxt->add("Last node");
  // No need to call delete, because destructor will clear heap
}