-5

当我了解到这一点时,我的理解是 C++ 关键字 delete 只能安全地删除由 new 分配的内存。我想知道您是否可以从函数中按值返回结构,然后在 main.xml 中将其删除。这是我要问的一个例子......

#include <stdio>
#include <new>
using namespace std;

struct structure {
   int i;
   float f;
}

struct get_struct();

int main() {
   structure structure_1;
   structure_1 = get_struct();

   delete &structure_1;
   return 0;
}

struct get_struct() {
   struct test_struct = new struct;
   return test_struct;
}

我知道我可以从函数返回一个指针并在 main 中分配一个指针以指向函数的返回值,这不是我要问的。我也尝试使用删除...

delete &struct;

这不起作用,我得到一个 Visual Studio 错误。

所以我要问的是,有没有人知道一种方法可以通过 new 值从函数中返回结构,并使用 delete 来释放 main 中的内存。也许这是一个非常简单的任务,但我很难过。感谢大家!

4

2 回答 2

0

一般部分

你的问题的一般答案是,你不能。

  • newanddelete运算符总是处理指针,而不是任何其他值类型。

  • 您将永远不必手动删除任何值类型,并且永远,永远,永远(!)永远都不应该尝试这样做。

原因是,用于存储任何值的内存是从主内存的不同部分分配的,与用于存储new操作员返回的指针指向的值的内存不同。

一旦程序流进入函数,用于存储函数中使用的值的内存位置称为堆栈将自动分配,并在函数离开后自动清理。

(当然,在内部有一些工作要做,但你永远不必自己处理它,因为编译器会生成所需的设置和清理代码)

new另一方面,用于存储使用运算符生成的指针值的内存是从根本不会自动清理的内存的另一部分(通常称为堆)分配的。

以你的例子

看一下您的示例代码:

struct get_struct() {
   struct test_struct = new struct;
   return test_struct;
}

第一个问题是,即使修复了一些语法错误:

struct structure get_struct() {
   struct structure test_struct = new structure;
   return test_struct;
}

该代码将无法编译,编译器会抛出一些错误,例如:

error: conversion from ‘structure*’ to non-scalar type ‘structure’ requested

因为new structure不使用该值,但只有指向该值的指针可用。要使两种类型都匹配,您必须使用struct strcuture *test_test = new structure;To 仍然按值返回,您可能会想到执行以下操作:

struct structure get_struct() {
   struct structure *test_struct = new structure;
   return *test_struct;
}

其中 in 将按值返回为 test_struct 分配的数据的副本。

这种方法的问题是,现在您已经产生了一个内存漏洞,正如您通过仔细查看将要发生的事情所看到的那样:

  • struct structure在进入函数时,将在堆栈上分配足够的内存来保存指向 a 的指针的值。
  • 操作员将new分配一些内存来保存堆上struct structure的a ,这是我已经讨论过的另一部分内存的通用名称。
  • 指向此内存位置的指针将存储在 test_struct

  • 将制作 test_struct 指向的结构结构的副本。

  • struct structure当进入函数时分配用于存储指针值的内存将被释放。

这种方法的问题是,在离开 get_structure 时只有指针,而不是指向的数据被返回给系统。由于您没有保留它的任何副本,因此内存实际上丢失了,因为没有机会delete再次在任何语句中引用它。

发生的事情如下:

             call to                    return
  main()    --------->  get_struct()    -------->
           get_struct()                            
 STACK
  +--------------+      +--------------+        +--------------+
  | structure_1; |      | structure_1  |        | structure_1  |
  +--------------+      +--------------+        +--------------+
  |              |      | ...          |        |              |
                        |              |
                        | test_struct *--+
                        +--------------+ | 
                        |              | |
                                         |              
 HEAP                                    |
                                         |
  |              |      |              | |      |              |
  |              |      +--------------+ |      +--------------+
  |              |      | structure    |<+      | structure    |
  |              |      | data         |        | data         |
  +--------------+      +--------------+        +--------------+

为了防止记忆丧失,你必须delete在离开之前get_structure()这样做,可能使用类似的东西:

struct structure get_struct() {
   struct structure *test_struct = new structure;
   struct ret = *test_struct;

   delete test_struct;
   return ret;
}
于 2013-03-30T22:26:42.253 回答
0

经过一番思考,我将正确的解决方案移至顶部:

struct S { int a; S(int a) : a(a) { } };
S foo () { return S(5); }

int main() {
    S s = foo();
}

此解决方案不会复制 S;它将被移动。由于它不涉及手动内存管理,因此更安全,因此被推荐。


如果这是一个愚蠢的任务,你绝对必须使用new

struct S {};

S* foo () { return new S; }

int main () {
    S* ptr = foo();
    delete ptr;
}

但它不被认为是现代 C++;您可以安全地按值返回,因为编译器会选择退出任何副本。

于 2013-03-30T21:13:01.117 回答