简体   繁体   English

使用make_shared通过shared_ptr包装动态数组

[英]Wrap dynamic array with shared_ptr by make_shared

I want to write some bytes to an array. 我想给数组写一些字节。 To make use of modern C++ I have decided to use a smart pointer. 为了利用现代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);
}

However, I am receiving the following compilation error: 但是,我收到以下编译错误:

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);

I am using g++ (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609 Is there a way to use smart pointers in such a situation? 我正在使用g++ (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609在这种情况下有没有办法使用智能指针?

Don't use std::make_shared with raw array, it won't construct an array as you expected, but will try to create a pointer to the type you specified, ie unsigned char[] . 不要将std::make_shared与原始数组一起使用,它不会像预期的那样构造数组,但会尝试创建指向您指定类型的指针,即unsigned char[] That's why you get a unsigned char (*)[] when use get() , as the error message said. 这就是为什么你在使用get()时得到一个unsigned char (*)[] ,正如错误消息所说的那样。

And std::shared_ptr will delete the pointer by delete by default, not delete[] , which should be used for array. std::shared_ptr将由删除指针delete缺省,不delete[]其应该被用于阵列。 You need to specify a customized deleter for it, but std::make_shared does not allow you to specify it. 您需要为其指定自定义删除器,但std::make_shared不允许您指定它。

You could (1) Initialize std::shared_ptr directly and specify the deleter, like 您可以(1)直接初始化std::shared_ptr并指定删除器,如

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

(2) Use std::unique_ptr instead, which provides a specified version for array, including call delete[] when deallocating and providing operator[] ( std::shared_ptr will support it from C++17). (2)改为使用std::unique_ptr ,它为数组提供了一个指定的版本,包括在解除分配和提供operator[]时调用delete[] operator[]std::shared_ptr将从C ++ 17支持它)。

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

(3) Consider about std::vector<unsigned char> and std::array<unsigned char> . (3)考虑一下std::vector<unsigned char>std::array<unsigned char>

I recommend you use std::vector<unsigned char> vec(512); 我建议你使用std::vector<unsigned char> vec(512); , wrapping contiguous dynamic arrays is exactly what it's for. 包装连续的动态数组正是它的用途。 Getting the raw buffer pointer is as simple as vec.data() ; 获取原始缓冲区指针就像vec.data() ;

If the vector needs to be shared, than you can still use a smart pointer 如果需要共享向量,则仍然可以使用智能指针

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

You'll get the benefit of reference counting with virtually no overhead due to using vector, and you'll get the entire vector API. 你会几乎没有开销获得引用计数的好处,由于使用矢量, 会得到整个向量API。

If you really want to use a shared_ptr with an array for this (rather than a vector as suggested by StoryTeller), your type should be unsigned char rather than unsigned char[] . 如果你真的想为这个使用带有数组的shared_ptr (而不是StoryTeller建议的向量),你的类型应该是unsigned char而不是unsigned char[] To make sure the array is correctly deleted, you need to specify an array deleter to pass to the shared_ptr constructor (so you can't use make_shared as this doesn't allow you to specify the deleter): 要确保正确删除数组,您需要指定一个数组删除器以传递给shared_ptr构造函数(因此您不能使用make_shared因为这不允许您指定删除器):

auto buf = std::shared_ptr<unsigned char>(new unsigned char[512], std::default_delete<unsigned char[]>());

You cannot use: 你不能使用:

std::make_shared<unsigned char[]>(512);

That because there is no template specialization for Type[] . 那是因为Type[]没有模板专门化 That because actually std::shared_ptr<T> does not support operator[] yet. 那是因为实际上std::shared_ptr<T> 还不支持operator[] It will in the new standard C++17 : 它将在新标准C ++ 17中

operator[] (C++17) operator [](C ++ 17)


A solution it could be using a STL container , or IMO better: std::unique_ptr . 它可以使用STL容器或IMO更好的解决方案: std::unique_ptr

Indeed, std::unique_ptr supports operator[] . 实际上, std::unique_ptr支持operator[]

Since C++14 , you can: 从C ++ 14开始 ,您可以:

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

It's exception-safe, almost 0 overhead, and it can be use as a array buffer. 它是异常安全的,几乎是0开销,它可以用作数组缓冲区。

Moreover the deallocation of the buffer is correctly handled by the correct call of delete[] operator. 此外,通过正确调用delete[]运算符可以正确处理缓冲区的释放。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM