std::make_unique<char>(size_t尺寸)和std::make_unique<char[]>(size_t尺寸)之间的区别?
Difference between: std::make_unique<char>(size_t size) and 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
here的文档,看不懂第(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]())
这是金螺栓 link: 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),因为数组元素未初始化。
您的代码“有效”是偶然的,使用“数组”中任何超过 1 个元素都会导致未定义的行为。
我正在实现循环数组数据结构,其代码如下所示:
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
here的文档,看不懂第(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]())
这是金螺栓 link: 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),因为数组元素未初始化。
您的代码“有效”是偶然的,使用“数组”中任何超过 1 个元素都会导致未定义的行为。