c++ - 区别: std::make_unique<char>(size_t size) 和 std::make_unique<char[]>(size_t size)?

标签 c++ c++11 c++17 c++14

我正在实现循环数组数据结构,其代码如下所示:

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)nd 签名的解释。任何人都可以帮助我了解差异以及为什么我的代码有效?
这是 (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]())这是金 bolt 链接: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 个元素都会导致未定义的行为。

关于c++ - 区别: std::make_unique<char>(size_t size) 和 std::make_unique<char[]>(size_t size)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67581410/

相关文章:

c++ - 使用迭代器按索引删除 vector ?

c++ - 如何让多个对象共享值?

c++ - C++ 17,初始化数组

c++ - 返回在transform中用lambda构造的对象

C++11 std::function const 重载歧义

c++ - std::vector 应该尊重 alignof(value_type) 吗?

c++ - operator= in c++(11)工作方向

c++ - 如何理解scoped_lock的析构函数?cppreference是不是出错了?

c++ - 当仿函数不是一个选项时,我如何在 C++ 中编写带有自定义函数调用的模板化 RAII 包装器?

c++ - 为什么成对注释不能放在 C++ 中的字符串中?