1 元素分配数组的正确 unique_ptr 声明

Proper unique_ptr declaration of 1 element allocated array

我需要使用一个 API 作为项目的一部分,该项目包括一个名为 ParamSet 的 class,其方法定义如下:

void AddString(const std::string &, std::unique_ptr<std::string[]> v, int nValues);

该方法的目的是向对象添加一个字符串数组来描述一些参数。例如,一个 ParamSet 对象可能需要一个指向 nValues 字符串数组的 "filename" 参数。

但是,当我尝试将方法 a unique_ptr 传递给仅包含 1 个字符串的数组时,除非我定义 unique_ptr 以特定方式。

以下代码在调用 Clear()return 时导致段错误。

ParamSet badparam;
badparam.AddString("filename", unique_ptr<string[]> (new string("test")), 1);
badparam.Clear(); // <------ CAUSES SEG FAULT

但是以下不会导致段错误。

ParamSet testparam;
std::unique_ptr<std::string[]> strings(new std::string[0]); // DOH, should be string[1]
strings[0] = std::string("test");
testparam.AddString("filename", std::move(strings), 1);
testparam.Clear(); // <------ NO SEG FAULT

我不明白为什么在调用 AddString 的行中创建 unique_ptr 会导致段错误,但在调用之外创建它却不会。

问题是您使用非数组 new 分配由 unique_ptr<T[]> 管理的内存,然后将继续使用数组 delete[],导致未定义的行为。

语法可以是:

badparam.AddString("filename", std::unique_ptr<std::string[]>(new std::string[1]{"test"}), 1);

std::unique_ptr 的数组特化要求使用 new[] 分配数组,因为它默认使用 delete[] 来释放数组。

在您的第一个示例中,您分配的是 new 的单个 std::string 对象,而不是 new[].

的单元素数组

在您的第二个示例中,您正在分配一个 0 元素数组 std::string,但您需要一个 1 元素数组。

试试这个:

std::unique_ptr<std::string[]> strings(new std::string[1]); // <-- NOT 0!
// Or, if you are using C++14:
// auto strings = std::make_unique<string[]>(1);
strings[0] = "test";
testparam.AddString("filename", std::move(strings), 1);

或者:

testparam.AddString("filename", std::unique_ptr<std::string[]>(new std::string[1]{"test"}), 1);