C:在函数内创建新对象并将其作为结果返回时,我是否必须使用new运算符来创建对象?

前端之家收集整理的这篇文章主要介绍了C:在函数内创建新对象并将其作为结果返回时,我是否必须使用new运算符来创建对象?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有两个虚拟的问题让我困惑了一段时间.我确实做了一些在线搜索并阅读了很多c教程,但是我找不到具体的答案.

假设我们有一个名为Node的类,它是单链表的构建块.

class Node
{
   int data;
   Node* next;
}

事实1:局部变量(非静态)将在相应函数退出时被销毁.

问题1:情况如何打击:

Node* func()
{ 
    Node n; 
    Node* ptr=&n; 
    return n;
}

节点n会被破坏吗?或者我们必须使用new运算符来创建节点并返回指向堆内存的指针.如果两种方式都有效,哪种方法更好?

问题2:如何为节点类编写析构函数? (我在stackOverflow上找到了一些类似的问题,但那些答案集中在链表的析构函数上.我已经得到了那个部分.我想要的只是Node类的析构函数).

—————————————感谢大家!我知道了 – – – – – – – – – – – – – – – – – –

感谢所有给我建议或指出我的错误的人.我想我得到了答案.以下是我从你的答案中得到的一个注释,这真的打败了我的困惑.

>从函数返回堆栈内存地址不是一个好习惯,因为它会导致未定义的行为.
>返回堆内存是可以的,但我们必须处理对象的破坏.
>另一种方法是返回一个对象,从复制构造函数中受益.

解决方法

问题1
Node* func() { Node n; Node* ptr=&n; return n;}

您的代码创建一个本地Node实例(在堆栈上),然后返回其地址.当函数返回时,作为局部变量的Node实例将被销毁.函数返回的地址现在指向具有未定义内容的某些内存,并且任何取消引用此指针的尝试都将导致未定义的行为.

为了创建节点,您实际上需要调用Node构造函数.如何返回结果与调用构造函数的方式有关.

>您可以按照尝试返回指针,在这种情况下,您需要使用new运算符:

Node* func() { 
  Node* pn = new Node(10); 
  return n;
}

但是,当您执行此操作时,您将为func调用方提供销毁相关对象的责任.由于new和delete是对称操作,因此将它们放在代码中的对称位置被认为是更好的形式,例如像这样:

void cnuf(Node* p) { 
  delete p; 
}

一个更好的替代方案可能是使用std :: shared_ptr,它为您提供引用计数,如下所示:

std::shared_ptr<Node> func() {
  return std::make_shared<Node>(10);
}

使用此方法,调用者无需手动管理每个节点的生命周期.另一种方法是使用std :: unique_ptr,它只允许单个对象所有权.
>或者您可以按值返回节点,您可以在本地创建它,然后让函数返回机制在您返回时复制它:

Node func() { 
  Node n(10); 
  return n;
}

问题2

您可以在Node类声明中声明这样的析构函数

class Node {
  ...
  ~Node();
}

然后,您可以像这样定义它:

Node::~Node() {
  ...
}

但是,实际上让列表管理其Node实例(下一个字段)之间的连接,并且只让Node类管理其成员数据的生命周期(数据字段)可能更好.

猜你在找的C&C++相关文章