通过 make_shared 用 shared_ptr 包装动态数组

新手上路,请多包涵

我想将一些字节写入数组。为了使用现代 C++,我决定使用智能指针。

 #include <memory>
#include <cstdint>

using namespace std;

void writeUint32_t(uint32_t value, unsigned char* p){
    *p     = static_cast<unsigned char>((value >> 24) & 0xFF);
    *(++p) = static_cast<unsigned char>((value >> 16) & 0xFF);
    *(++p) = static_cast<unsigned char>((value >>  8) & 0xFF);
    *(++p) = static_cast<unsigned char>((value      ) & 0xFF);
}

int main(){
    auto buf = make_shared<unsigned char[]>(512);
    uint32_t data = 1234;
    writeUint32_t(data, buf.get() + 8);
}

但是,我收到以下编译错误:

 u.cpp:15:37: error: invalid use of array with unspecified bounds
 writeUint32_t(data, buf.get() + 8);
                                 ^
u.cpp:15:38: error: cannot convert ‘unsigned char (*)[]’ to ‘unsigned char*’ for argument ‘2’ to ‘void writeUint32_t(uint32_t, unsigned char*)’
 writeUint32_t(data, buf.get() + 8);

我正在使用 g++ (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609 在这种情况下有没有办法使用智能指针?

原文由 robert 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

我建议您使用 std::vector<unsigned char> vec(512); ,包装连续动态数组正是它的用途。获取原始缓冲区指针就像 vec.data() 一样简单;

如果需要共享向量,您仍然可以使用智能指针

auto p_vec = make_shared<vector<unsigned char>>(512);

由于使用向量,您将获得引用计数的好处,几乎没有开销, 并且 您将获得整个向量 API。

原文由 StoryTeller - Unslander Monica 发布,翻译遵循 CC BY-SA 3.0 许可协议

不要将 std::make_shared 与原始数组一起使用,它不会按您的预期构造数组,但会尝试创建指向您指定的类型的指针,即 unsigned char[] 。这就是为什么您在使用 get() unsigned char (*)[] 的原因,如错误消息所述。

std::shared_ptr 默认会通过 delete 删除指针,而不是 delete[] 应该用于数组。您需要为其指定自定义删除器,但 std::make_shared 不允许您指定它。

您可以(1)直接初始化 std::shared_ptr 并指定删除器,例如

std::shared_ptr<unsigned char> buf(new unsigned char[512], [](unsigned char* p)
{
    delete[] p;
});

(2) 使用 std::unique_ptr 代替,它为数组提供了一个指定的版本,包括调用 delete[] 释放和提供 operator[] ( std::shared_ptr 从 C++17 开始支持它)。

 auto buf = std::make_unique<unsigned char[]>(512);

(3) 考虑 std::vector<unsigned char>std::array<unsigned char>

原文由 songyuanyao 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题