C++使用 RAII 创建数组

C++ using RAII to create an array

本文关键字:数组 创建 RAII 使用 C++      更新时间:2023-10-16

在C++中创建数组时有没有办法使用 RAII,还是必须通过"new"关键字进行手动内存管理?

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

首先我的免责声明:我在C++相当新手。

现在详细介绍:我只是想遍历一个现有的数组,SomeClass source[],并将每个元素解析成一个存储数组,字符串结果[]。

因此,要创建存储字符串结果[],我是否需要说string results[] = new string[source.size()]或者有没有办法通过 RAII 技术避免这里的"new"关键字?

听起来我听到矢量是要走的路。 不过,想知道使用普通的旧数组是否可行。

在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]);

上述myArray管理的阵列将在销毁时正确删除delete []

由于没有unique_ptr类似shared_ptrmake_shared,你要么必须使用new来实际构造数组,要么提供你自己(或别人(的make_unique实现


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


1"你应该使用 std::vector<>除非您了解其他容器并且有令人信服的理由不这样做">

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

>std::vector<T>是RAII数组类型。从您提供的其他信息中std::vector<string>适合您使用。


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

就像关于数组的旁白一样,此语法不适合C++。教授 C 和 C++ 的人经常教导数组和指针是一回事,但事实并非如此,上面的语法显示了它们的不同之处之一。

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

  • 数组和指针是不同的类型
  • 在许多情况下,应用了从数组到指针的隐式转换。转换结果为数组第一个元素的地址。
  • 指针
  • 算术的定义是,如果指针指向数组中的元素,则可以通过对指针值进行加减来获取指向数组其他元素的指针。
  • 在某些上下文中,编写数组类型将产生指针类型。特别是,声明为数组类型的函数参数将调整为指针类型。F.D. void foo(int[10]);实际上与void foo(int*);相同。

因此,您显示的代码是声明一个数组并使用指针对其进行初始化。这将导致错误,因为没有从指针到数组的转换。

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

您可以使用

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

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

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 对象会自动强制转换为其成员指针。