std::make_unique<char>(size_t size) 和 std::make_unique<char[]>(size_t size)之间的区别?



我实现了循环数组数据结构,其代码如下:

struct CircularArrayException : public std::exception {
std::string msg;
CircularArrayException(const std::string arg_msg) 
: msg{"CircularArrayException: " + arg_msg} {}
const char * what () const throw () {
return msg.c_str();
}
};
template <typename T>
class CircularArray {
public:
const size_t array_size;
std::unique_ptr<T> uptr_arr;
size_t occupied_size = 0;
int front_idx = -1;
int back_idx = -1;

CircularArray(const CircularArray& ca) = delete;
CircularArray& operator=(const CircularArray& ca) = delete;
CircularArray(
const size_t arg_array_size
):  array_size{arg_array_size} {
uptr_arr = std::make_unique<T>(array_size);
};
};

在实现之后,我用CircularArray<char>测试了实现,它工作得很好。但是,后来我意识到,我们使用std::make_unique<char[]>(num_elements)向数组声明unique_ptr,而不是std::make_unique<char>(num_elements)。但是,即便如此,代码似乎也能正常工作。我在这里看了std::make_unique的文档,无法理解第(2(个签名的解释。有人能帮助我理解其中的区别以及为什么我的代码可以工作吗?

以下是(2(签名的cppreference上所写的内容:

template< class T >
unique_ptr<T> make_unique( std::size_t size );

(2( (从C++14开始((仅适用于边界未知的数组类型(

构造未知边界T的数组。只有当T是未知边界的数组时,此重载才会参与重载解析。该功能等效于:unique_ptr<T>(new typename std::remove_extent<T>::type[size]())

以下是goldbolt链接:https://godbolt.org/z/K9h3qTeTW

std::make_unique<char>(65);创建一个指针,指向用值65('A'(初始化的单个字符。std::make_unique<char[]>(65)创建了一个包含65个元素的数组。

如果你运行这个代码:

#include <memory>
#include <iostream>
int main()
{
auto a = std::make_unique<char>(65);
std::cout << *a << "n";
auto b = std::make_unique<char[]>(65);
std::cout << (int)b[0] << "n";
}

当数组元素未初始化时,它将为第一个打印A,为第二个打印未定义的值(可能为0(。

您的代码";作品";偶然地使用您的";阵列";将导致未定义的行为。

最新更新