如何释放结构内部的指针?
我对结构很陌生,所以请耐心等待。我编写了一个名为 gnt 的结构,其中包含一个整数指针、一个整数和一个布尔值:
struct gnt
{
unsigned int* num;
unsigned int size;
bool negative;
};
因为我将任意长度的 int 数组分配给各种 gnt 变量(即 k.num = new int*[j]
)(对于某些值j
),我需要以某种方式释放它们。我不知道该怎么做。我是否只需使用 delete[] k.num;
(其中 k 是 gnt)?我需要担心结构本身吗?
另外,作为一个附带问题,我编写了一个递归函数来乘以列表中的项目:
char* chain_multi(char** list, unsigned int start, unsigned int end)
{
/***************************************************************
This function recursively multiply every items in a list then
return the product.
***************************************************************/
unsigned int size = start - end + 1;
if(size == 1)
return copy_char(list[end]);
if(size == 2)
return multiplication(list[start], list[end]);
int rs = start - size / 2;
char* right = chain_multi(list, rs, end);
char* left = chain_multi(list, start, rs + 1);
char* product = multiplication(left, right);
delete[] left;
delete[] right;
return product;
}
这与不使用递归相比是否有任何优势?我测试了各种大小的列表(10 - 10000 个条目之间),似乎在时间上没有任何优势......不过,递归代码比其对应代码短。
感谢您的任何意见。
I'm new to structures so please bear with me. I wrote a structure called gnt containing an integer pointer, an integer, and a boolean:
struct gnt
{
unsigned int* num;
unsigned int size;
bool negative;
};
Because I am allocating arbitrary length int arrays to various gnt variables (ie. k.num = new int*[j]
) (for some value j
), I need to free them somehow. I am not sure how to do that. Do I simply use delete[] k.num;
(where k is a gnt)? Do I have to worry about the structure itself?
Also, as a side question, I wrote a recursive function to multiply out items in a list:
char* chain_multi(char** list, unsigned int start, unsigned int end)
{
/***************************************************************
This function recursively multiply every items in a list then
return the product.
***************************************************************/
unsigned int size = start - end + 1;
if(size == 1)
return copy_char(list[end]);
if(size == 2)
return multiplication(list[start], list[end]);
int rs = start - size / 2;
char* right = chain_multi(list, rs, end);
char* left = chain_multi(list, start, rs + 1);
char* product = multiplication(left, right);
delete[] left;
delete[] right;
return product;
}
Will this give any advantage over doing it without recursion? I tested with various sized lists (between 10 - 10000 entries) and there doesn't seem to be any advantage time wise... The recursive code is shorter than its counterpart though.
Thanks for any input.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
由于您使用的是 C++,因此您可以在结构中放置一个析构函数来自动为您执行此操作。还有其他方法,但这是最实用的:
我还建议有一个构造函数来确保 num 在初始化之前具有 null,因此析构函数将在此之前安全地工作:
在分配实例时具有安全的行为或者在创建时初始化,需要复制构造函数和赋值运算符。他们应该复制所有非动态成员的值,并创建具有相同大小和内容的 num 副本。在这种情况下,还建议初始化构造函数中的所有成员,因为 size 也应该始终具有有效的内容才能发挥作用。如果您现在不想让事情变得太复杂,只需将它们设为私有即可,如果您尝试执行(不支持的)对象分配或复制,这将导致编译器发出警告:
正如其他人所建议的,一种替代方法是使用 std: :向量而不是原始指针。这样,您就不需要担心释放:
关于“我是否必须担心结构本身?”的问题,这取决于您如何创建其实例。如果是 new 操作员,是的。如果不是,当它们像任何其他变量一样超出范围时,它们将被释放。
最后,关于递归,IMO 很少选择与代码效率有关的选择。仅当代码变得更简单/更清晰并且不存在不利影响(如堆栈溢出)的危险时,才应使用递归。如果不是这种情况,我总是会选择迭代版本。
Since you're using c++, you can put a destructor in the struct to do that automatically for you. There are other ways, but this is the most practical:
I'd also suggest to have a constructor to make sure that num has null until it's initialized, so the destructor will work safely before that:
To have a safe behavior when instances are assigned or initialized when created, you need the copy constructor and assignment operator. They should copy the values of all the non-dynamic members, and create a duplicate of num with the same size and contents. In such case, it'd be also recommended to initialize all the members in the constructor, because size should also always have a valid content for that to work. If you don't want to complicate things too much now, just make them private, this will cause the compiler to bark if you try to do an (unsupported) object assignment or copy:
As others suggested, one alternative is to use std::vector instead of a raw pointer. That way, you don't need to worry about deallocations:
About the question "do I have to worry about the structure itself?", that depends on how you created its instances. If it was with operator new, yes. If not, they'll be deallocated when goin out of scope as any other variable.
Finally, about the recursion, IMO rarely the choice is about code efficiency. You should use recursion only if the code becomes simpler/cleaner AND there is no danger of adverse effects (like stack overflow). If that's not the case, I'd always go for the iterative version.
遵守规则:
您应该将与从
new[]
收到的相同地址传递给delete[]
。如果您只在 freestore 上分配了一个成员,那么您只需要取消分配该成员。
您使用
new []
分配了成员k.num
,因此您应该仅为它调用delete []
。另外,您可以使用
std::vector
而不用自己进行内存管理(除非这是一些限制您这样做的蹩脚分配)对于 Standerdese 粉丝:
标准 C++03 § 3.7.4.2-3:
Follow the Rule:
You should pass the same address to
delete[]
that you received fromnew[]
.If You allocated only a member on freestore, so you would need to deallocate only that.
You allocated the member
k.num
usingnew []
, so yes you should calldelete []
only for it.Also, You can use
std::vector
instead of doing the memory management by yourself(unless this is some crappy assignment which restricts you from doing so)For Standerdese Fans:
Standard C++03 § 3.7.4.2-3:
递归的通常优点是简单和清晰(并且可能是解决问题的不同方法),通常不是速度。事实上,过去的情况恰恰相反:递归实现往往比迭代实现慢得多。现代硬件已经消除或大大减少了这种速度差异,但递归实现比迭代实现更快仍然是相当不寻常的。
The usual advantage of recursion is simplicity and clarity (and possibly a different approach to a problem), not normally speed. In fact, rather the opposite used to be true: recursive implementations tended to be noticeably slower than iterative ones. Modern hardware has eliminated or drastically reduced that speed differential, but it would still be fairly unusual for a recursive implementation to be faster than an iterative counterpart.
free
适用于任何指针,无论它是否是结构成员。如果您正在编写 C 代码,也许使用malloc()
和free()
会更好。是否递归取决于上下文。一般来说递归是可以的。由于一些函数调用和参数传递开销,递归稍微慢一些。递归的问题在于,如果您的递归级别非常深(可能有 1000 个嵌套函数调用),您最终可能会填满堆栈。这会导致程序崩溃。
free
is fine on any pointer disregarding the fact it is a structure member or not. If you are writing C code maybe it would be better to usemalloc()
andfree()
.For recursion or not it depends on the context. Generally speaking recursion is ok. Recursion is slightly slower because of some function calling and parameter passing overhead. The problem with recursion is that if you go very deep in recursion level (maybe 1000 nested function call) you could end up filling the stack. This would cause the program to crash.