在我的代码中,我使用当前以这种方式分配的缓冲区:
char* buf1 = (char*)malloc(size);
但是,在代码中的某些点上,我想将指针重新分配给内存中的其他位置。问题是代码中还有其他地方仍需要访问指针buf1。
用C ++做到这一点的最佳方法是什么?现在,我正在考虑编写一个带有单个char *的结构,然后分配该结构类型的对象并将其传递到需要的地方,并引用包装后的指针以获取buf1的当前值。>
但是,这似乎与unique_ptr相似。如果我使用unique_ptr,如何将char *包装起来?我对此进行测试时遇到了一些麻烦,但不确定它是否受支持。
为了澄清:这些缓冲区是大小不同的字节。
答案 0 :(得分:3)
通常,此问题无法回答。数组char
可能想做的事情太多了。在不知道您实际想要做什么的情况下,无法说出可能使用的好的抽象方法……
如果您想使用字符串做东西,只需使用std::string
。如果您希望动态大小的缓冲区可以增长和缩小,请使用std::vector
。
如果您只需要一个字节缓冲区,该缓冲区的大小在运行时确定,或者通常只想在动态存储中使用,我将使用std::unique_ptr
。尽管std::unique_ptr<T>
仅用于单个对象,但部分特殊化std::unique_ptr<T[]>
可用于处理动态分配的数组。例如:
auto buffer = std::unique_ptr<char[]> { new char[size] };
通常,建议通过new
创建对象并获得std::unique_ptr
的方法是使用std::make_unique。而且,如果要将缓冲区初始化为某个特定值,则确实应该使用std::make_unique<char[]>(value)
。但是,std::make_unique<T[]>()
将对它创建的数组的元素进行值初始化。对于char
数组,这实际上意味着您的数组将被零初始化。以我的经验,不幸的是,即使整个缓冲区在创建后立即被覆盖,编译器也无法优化零初始化。因此,如果为了避免初始化的开销而需要一个未初始化的缓冲区,则不能使用std::make_unique
。理想情况下,您只需定义自己的函数即可通过new
创建一个默认初始化的数组,并为其获取一个std::unique_ptr
,例如:
template <typename T>
inline std::enable_if_t<std::is_array_v<T> && (std::extent_v<T> == 0), std::unique_ptr<T>> make_unique_default(std::size_t size)
{
return std::unique_ptr<T> { new std::remove_extent_t<T>[size] };
}
然后
auto buffer = make_unique_default<char[]>(new char[size]);
似乎C ++ 20将以std::make_unique_default_init
的形式包含此功能。因此,那将是首选方法。
请注意,如果要处理普通std::unique_ptr
,则仍然必须分别传递缓冲区的大小。如果您打算绕过缓冲区,则可能需要捆绑std::unique_ptr
和std::size_t
template <typename T>
struct buffer_t
{
std::unique_ptr<T[]> data;
std::size_t size;
};
请注意,类似于上面struct的内容表示缓冲区的所有权。因此,例如在从工厂函数返回新缓冲区时,例如,
buffer_t makeMeABuffer();
或将缓冲区的所有权移交给其他人,例如
DataSink(buffer_t&& buffer)
您不希望使用它只是将某些功能指向缓冲区数据,并且大小可以在不转移所有权的情况下进行一些处理。为此,您只需传递一个指针和大小,或者例如使用span(从C ++ 20开始;也可以作为GSL的一部分使用)…