使用在C ++中动态分配的数组有什么问题? [英] What is wrong with using arrays dynamically allocated in C++?

查看:152
本文介绍了使用在C ++中动态分配的数组有什么问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

像下面的代码:

int size = myGetSize();
std::string* foo;
foo = new std::string[size];
//...
// using the table
//...
delete[] foo;



我听说这种使用(不是这个代码,而是动态分配整体)在某些情况下,应仅与RAII一起使用。为什么?

I heard that such use (not this code precisely, but dynamic allocation as a whole) can be unsafe in some cases, and should be used only with RAII. Why?

推荐答案

我看到您的代码有三个主要问题:

I see three main problems with your code:


  1. 使用裸体,拥有指针。

  1. Use of naked, owning pointers.

使用裸体 $ c>。

Use of naked new.

使用动态数组。


$ b b

由于其自身原因,每个都是不希望的。我会尝试依次解释每一个。

Each is undesirable for its own reasons. I will try to explain each one in turn.

(1)违反我喜欢调用子表达式正确性违反了语句正确性 。这里的想法是,没有语句,甚至不是任何子表达式,本身应该是一个错误。我把错误一词宽松地表示为可能是一个错误。

(1) violates what I like to call subexpression-wise correctness, and (2) violates statement-wise correctness. The idea here is that no statement, and not even any subexpression, should by itself be an error. I take the term "error" loosely to mean "could be a bug".

编写好代码的想法是,如果它出错了,故障。你的基本心态应该是偏执的懦夫。根本不编写代码是实现这一点的一种方法,但是由于很少满足要求,下一个最好的事情是确保无论你做什么,这不是你的故障。唯一可以系统地证明这不是您的错误的方法是,如果您的代码中没有一个部分是错误的根本原因。现在让我们再次查看代码:

The idea of writing good code is that if it goes wrong, it wasn't your fault. Your basic mindset should be that of a paranoid coward. Not writing code at all is one way to achieve this, but since that rarely meets requirements, the next best thing is to make sure that whatever you do, it Isn't Your Fault. The only way you can systematically prove that it's not your fault is if no single part of your code is the root cause of an error. Now let's look at the code again:


  • new std :: string [25] 是一个错误,因为它创建一个动态分配的对象被泄漏。

  • new std::string[25] is an error, because it creates a dynamically allocated object which is leaked. This code can only conditionally become a non-error if someone else, somewhere else, and in every case, remembers to clean up.

这需要,首先,这个代码只能有条件地成为一个非错误,如果别人,别的地方,在任何情况下,这个表达式的值存储在某个地方。这是发生在你的情况,但在更复杂的表达式可能很难证明它会发生在所有情况下(未指定的评估顺序,我在看你)。

This requires, first of all, that the value of this expression be stored somewhere. This is happening in your case, but in more complex expressions it may be hard to prove that it will ever happen in all cases (unspecified evaluation order, I'm looking at you).

foo = new std :: string [125]; 是错误,因为 foo 泄漏资源,除非星星对齐,有人记住,在每种情况下,在正确的时间,清理。

foo = new std::string[125]; is an error because again foo leaks a resource, unless the stars align and someone remembers, in every case and at the right time, to clean up.

到目前为止,编写此代码的正确方法是:

The correct way of writing this code so far would be:

std::unique_ptr<std::string[]> foo(std::make_unique<std::string[]>(25));

请注意,此语句中的每个子表达式程序错误。这不是你的错误。

Note that every single subexpression in this statement is not the root cause of a program bug. It Is Not Your Fault.

最后,对于(3),动态数组在C ++中是一个错误,应该基本上不会使用。有几个标准缺陷只涉及动态数组(并不认为是值得修复)。简单的说法是,你不能使用数组而不知道它们的大小。您可能会说,您可以使用哨兵或墓碑值动态标记数组的结尾,但这会使您的程序的正确性 - 依赖,而不是类型依赖,因此不是静态检查(不安全的定义)。你不能静态地断言这不是你的错误。

Finally, as for (3), dynamic arrays are a misfeature in C++ and should basically never be used. There are several standard defects relating just to dynamic arrays (and not considered worth fixing). The simple argument is that you cannot use arrays without knowing their size. You might say that you could use a sentinel or tombstone value to mark the end of an array dynamically, but that makes the correctness of your program value-dependent, not type-dependent, and thus not statically checkable (the very definition of "unsafe"). You cannot assert statically that It Wasn't Your Fault.

所以你最终不得不为数组大小维护一个单独的存储。你猜测什么,你的实现必须重复的知识,所以它可以调用析构函数,当你说 delete [] ,这样浪费了重复。相反,正确的方法不是使用动态数组,而是从元素方面的对象构造中分离内存分配(并通过分配器自定义为什么我们在它)。

So you end up having to maintain a separate storage for the array size anyway. And guess what, your implementation has to duplicate that knowledge anyway so it can call destructors when you say delete[], so that's wasted duplication. The correct way, instead, is not to use dynamic arrays, but instead separate memory allocation (and make it customizable via allocators why we're at it) from element-wise object construction. Wrapping all this (allocator, storage, element count) into a single, convenient class is the C++ way.

因此,你的代码的最终版本是这样的:

Thus the final version of your code is this:

std::vector<std::string> foo(25);

这篇关于使用在C ++中动态分配的数组有什么问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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