C ++:在函数中创建新对象并返回结果时,是否必须使用new运算符创建对象? [英] C++:When creating a new objects inside a function and returning it as result, must I use the new operator to create the object?

查看:305
本文介绍了C ++:在函数中创建新对象并返回结果时,是否必须使用new运算符创建对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个虚拟的问题使我困惑了一段时间。我确实在网上做了一些搜索并阅读了很多C ++教程,但是找不到具体答案。

I have two dummy questions which have confused me for a while. I did do some searching online and read through much c++ tutorials, however I cannot find concrete answers.

说我们有一个名为Node的类,它是一个单独的构建块

Say we have a class named Node which is a building block of a singly linked list.

class Node
{
   int data;
   Node* next;
}

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

Fact1: local variables(non static) will be destroyed upon the exit of the corresponding functions.

问题1:情况如何?

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

节点n是否会被销毁?或者我们必须使用new运算符创建节点并返回指向堆内存的指针。如果这两种方法都可行,哪种方法更好?

Will the node n be destroyed? Or we have to use the new operator to create the node and return a pointer to a heap memory. If both ways work, which one is a better approach?

问题2:如何为节点类编写析构函数? (我在stackOverflow上发现了一些类似的问题,但这些答案集中在链接列表的析构函数上。我已经掌握了这一部分。我想要的正是Node类的析构函数。)

Question2: How to write a destructor for the node class? (I find some similar questions on stackOverflow, but those answers focused on the destructor for the linked list. I already got that part. What I want is exactly a destructor for a Node class).

---------------------------------------编辑----- -------------------------------

---------------------------------------EDIT------------------------------------

感谢所有给予的人给我建议或指出我的错误。我想我得到了答案。以下是我从您的答案中得到的注释,它确实消除了我的困惑。

Thank all who gave me suggestions or pointed out my errors. I think I got my answers. Below is a note taken by me from your answers and that really knock out my confusions.


  1. 返回堆栈不是一个好习惯函数的内存地址,因为它将导致未定义的行为。

  2. 返回堆内存是可以的,但是我们必须注意对象的销毁。

  3. 另一种方法是返回对象,从而受益从复制构造函数。


推荐答案

问题1

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

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

Your code creates a local Node instance (on the stack), then returns its address. When the function returns, the Node instance, being a local variable, is destroyed. The address the function returned now points to some memory with undefined contents, and any attempts at dereferencing this pointer will lead to undefined behavior.

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

In order to create a node, you actually need to call a Node constructor. How you want to return the result is relevant to how you call the constructor.


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

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

但是,当您这样做时,会给出 func 调用者有责任销毁相关对象。由于 new delete 是对称操作,因此将它们放在代码中的对称位置被认为是更好的形式,例如像这样:

However, when you do this, you give func callers the responsibility to destroy the object in question. Since new and delete are symmetrical operations, it is considered better form to put them in symmetrical places in your code, e.g. like this:

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

一个更好的选择是使用 std :: shared_ptr ,它为您提供引用计数,例如:

A better alternative altogether may be to use std::shared_ptr which gives you reference counting, like this:

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

使用此方法,调用者无需手动管理每个节点的生命周期。另一种选择是使用 std :: unique_ptr 代替,它仅允许单个对象所有权。

Using this approach, the callers do not need to manually manage each node's lifecycle. Another alternative is using std::unique_ptr instead, which only allows single object ownership.

或者您可以按值返回节点,在这种情况下,您可以在本地创建该节点,然后让函数返回机制在返回时创建一个副本:

Or you can return the node by value, in which case you create it locally, and then let the function return mechanisms make a copy when you return it:

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



问题2

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

You can declare a destructor like this in your Node class declaration:

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

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

Then, you can define it like this:

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

但是,最好让列表管理其 Node 实例之间的连接( next 字段),只允许 Node 类管理其成员数据的生命周期( data 字段)

However, it is probably better to actually let the list managed the connection between its Node instances (next field), and only let the Node class manage the lifecycle of its member data (data field)

这篇关于C ++:在函数中创建新对象并返回结果时,是否必须使用new运算符创建对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆