如何在传递引用而不是指针时为链表分配内存?

时间:2011-06-15 23:47:51

标签: c++ reference

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

例如:

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 ++)

3 个答案:

答案 0 :(得分:3)

应该是

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) /* ... */ { }
};

这样的节点将“通过引用”存储其后继者;但你必须用现有节点初始化它! (没有“null”引用这样的东西。)Poultry-Oval 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("!");
}

答案 1 :(得分:2)

main()的第二个版本中,您要拨打add(aNode)两次。但是你每次都提供相同的参数。因此,虽然您正在创建两个新的node对象,但其中一个永远丢失(内存泄漏)。而aNode.next最终指向另一个。 aNode.next->next不是有效指针,因此当您尝试通过它访问某些内容时会出现seg-fault。

根据您想要达到的目标,您可以尝试:

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

有更好的方法来进行链表,但这至少可以避免seg-fault。

答案 2 :(得分:1)

尝试

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
}