3

有没有办法在 C++ 中创建数组时使用 RAII,还是我必须通过“new”关键字求助于手动内存管理?

编辑:根据要求,一些额外的细节:

首先我的免责声明:我是 C++ 的新手。

现在详细说明:我只是想遍历现有数组 SomeClass source[],并将每个元素解析为存储数组 string results[]。

因此,要创建该存储字符串结果 [],我需要说string results[] = new string[source.size()]还是有办法通过 RAII 技术避免此处的“新”关键字?

听起来我听说矢量是要走的路。不过,想知道是否可以使用普通的旧阵列。

4

4 回答 4

11

在 C++ 中,尤其是在讨论 RAII 时,我们真的根本不应该使用 C 风格的数组。标准库提供了许多具有不同属性的容器,这些属性消除了对 C 样式数组的大多数需求。默认情况下,您应该使用std::vector<>,除非您了解其他容器并且有令人信服的理由不使用1

从您的评论来看,您似乎正在尝试构建一个字符串数据数组。这在现代 C++ 中很简单——只需使用std::vector <std::string>.

int main()
{
  std::vector <std::string> myStrings;
  myStrings.push_back ("hello");
  myStrings.push_back ("goodbye");
}

这实现了您提到的所有成为 RAII 的目标,并且不需要newdelete任何东西。它还与其他标准库工具(例如find.

我确实说过“消除大多数需求”,强调我的。仍然偶尔需要去老学校。我不会在这里讨论它们,因为如果你真的需要它,你已经知道了。也就是说,如果你不知道你可能不需要它。

话虽如此,std::unique_ptr 确实支持使用特殊语法管理 C 样式数组:

std::unique_ptr <unsigned []> myArray (new unsigned [256]);

上面管理的数组myArraydelete []在销毁时正确删除。

由于没有unique_ptrshared_ptr's 的类似物make_shared您要么必须使用new实际构造数组,要么提供您自己(或其他人)的实现make_unique


侧边栏: make_unique将添加到 C++14。


1 “你应该使用 std::vector<> 除非你了解其他容器并且有一个令人信服的理由不使用”

这不仅仅是我的意见。这也是整个StackOverflow 、C++ 的创建者 Bjarne Stroustup 和 C++ 标准本身 (23.1.1) 的一般(非官方)意见。

于 2013-10-11T15:18:39.363 回答
4

std::vector<T>是一个 RAII 数组类型。根据您提供的附加信息std::vector<string>,您可以使用它。


string results[] = new string[source.size()]

顺便说一句,这种语法对于 C++ 是不正确的。教授 C 和 C++ 的人经常说数组和指针是同一个东西,但事实并非如此,上面的语法显示了它们不同的一种方式。

数组和指针之间的实际关系是

  • 数组和指针是不同的类型
  • 在许多情况下,应用了从数组到指针的隐式转换。转换结果是数组第一个元素的地址。
  • 指针算法的定义是,如果指针指向数组中的一个元素,那么您可以通过对指针值进行加减来获得指向数组其他元素的指针。
  • 在某些情况下,写入数组类型将导致指针类型。特别是,声明为数组类型的函数参数被调整为指针类型。例如void foo(int[10]);,实际上等同于void foo(int*);

所以你展示的代码是声明一个数组并用一个指针初始化它。这将导致错误,因为没有从指针到数组的转换。

一般来说,你应该避免在 C++ 中使用原始数组;数组只是有太多奇怪的规则,例如上面描述的奇怪的函数参数规则,关于何时执行隐式转换的规则,禁止赋值和从函数返回数组等。开始时最好坚持std::array在编译时已知大小的数组的模板和在编译时未知大小的数组的std::vector模板。

于 2013-10-11T15:10:45.577 回答
0

您可以使用std::vector<string>并将push_back()每个结果字符串放入向量中。除非您想避免使用向量并自己管理内存,否则您不必使用 new

于 2013-10-11T15:26:24.360 回答
0

我认为一个简单的模板在一般情况下可以解决问题:

template<class T>
class HeapArray {
    T* ptr = nullptr;
public:
    HeapArray(int size) { ptr = new T[size]; }
    ~HeapArray() { delete [] ptr; }
    operator T*() { return ptr; }
};

您将其用作:

HeapArray<std::string> results(source.size());
results[i] = "how cool is this";

基本上 HeapArray 对象会自动转换为它的成员指针。

于 2021-03-05T01:30:09.340 回答