【发布时间】:2021-05-18 07:02:06
【问题描述】:
我正在实现循环数组数据结构,其代码如下所示:
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_uniquehere 的文档,无法理解(2)nd 签名的解释。谁能帮我理解其中的区别以及我的代码为何有效?
以下是 cppreference 上 (2) 签名的内容:
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]())
这里是金螺栓链接:https://godbolt.org/z/K9h3qTeTW
【问题讨论】:
-
你是在 Valgrind 这样的内存调试器中运行的吗?无论如何,我不认为
make_unique()带有大小参数,因此该参数仅用于初始化创建的对象。只需使用调试器单步调试代码,即可在 cppreference.com 上查找或研究文档。顺便说一句:当您可以在vector上构建时,我会质疑您选择使用这样的动态分配。考虑在 codereview.stackexchange.com 提交您的代码(一旦它正常工作)。 -
你的问题的代码太多了!尝试一个最小且易于重现的代码,其中仅包含两个唯一指针:) 这将激励人们更多地阅读和回答您的问题 :)))
-
感谢 cmets。我会尽量减少这个问题。
-
vector是一个更好的选择,我会使用它。但是,我仍然想知道make_unique的这个(2)签名是什么意思。 -
@UlrichEckhardt make_unique 接受 size 参数,如果类型是未知边界的数组。