包装二进制缓冲区 - 可能没有多余的移动/复制?

Wrapping binary buffers - possible without extraneous moving/copying?

本文关键字:多余 移动 复制 缓冲区 二进制 包装      更新时间:2023-10-16

公平警告,我是一个C++新手。因此,我的部分或全部假设可能是错误的。

请考虑以下事项:

#include <cstddef>
#include <cstdio>
template <typename T>
class StaticData {
private:
const T* data = nullptr;
std::size_t size;
public:
StaticData(const T* data, std::size_t size) : data(data), size(size) { }
const T* GetData() {
return this->data;
}
std::size_t GetSize() {
return this->size;
}
};
const unsigned char foo[] = { 0x66, 0x6F, 0x6F };
// Possible to initialize this class with data directly?
StaticData<unsigned char> SDFoo = StaticData<unsigned char>(foo, sizeof(foo));
int main() {
std::printf("%p (%lu)n", foo, sizeof(foo));
std::printf("%p (%lu)n", SDFoo.GetData(), SDFoo.GetSize());
}

使用此代码,我将foo包装在一个包含数据及其值的(不完整)类中。 我对修改包含的数据没有兴趣,我只是想要一个大小始终可用的安全包装器。 我首先尝试了std::array,但它有一个不幸的副作用,即使大小成为其类型的一部分,并且我无法将不同大小的数组放在容器中,例如std::unordered_map

这种方法的唯一问题是foo仍然在全球范围内徘徊。 为了安全起见,我宁愿容器类SDFoo是唯一可见的东西(也许Foo)。 但是,我无法找到一种方法来摆脱foo,而不会在静态初始化时引入不必要的移动或复制整个缓冲区。

有什么想法吗?

编辑:为了清楚起见,我想知道是否有办法以某种方式摆脱额外的foo变量。

从全局内存中消除foo变量的唯一方法(据我所知)是在StaticData对象本身内部分配数据的副本。 您可以使用std::shared_ptr(允许您制作StaticData的副本而不制作其数据的额外副本)和std::initializer_list来帮助您,例如:

#include <initializer_list> 
#include <memory> 
template <typename T>
class StaticData {
private:
const T* m_data;
std::size_t m_size;
std::shared_ptr<T[]> m_storage;
public:
StaticData(const T* data, std::size_t size)
: m_data(data), m_size(size)
{
}
StaticData(const std::initializer_list<T> &data)
: m_storage(new T[data.size()]), m_data(m_storage.get()), m_size(data.size())
{
std::copy(data.begin(), data.end(), m_storage.get());
}
const T* GetData() const
{
return m_data;
}
std::size_t GetSize() const
{
return m_size;
}
};
StaticData<unsigned char> SDFoo({ 0x66, 0x6F, 0x6F });
void bar(const char *str)
{
StaticData<char> SDBar(str, strlen(str));
std::printf("SDBar: %p (%lu)n", SDBar.GetData(), SDBar.GetSize());
}
int main()
{
std::printf("SDFoo: %p (%lu)n", SDFoo.GetData(), SDFoo.GetSize());
bar("baz");
return 0;
}

所以你要找的是任意数据的常量视图,其中数据本身是私有的?也许像这样:

// foo.h
extern StaticData<const unsigned char> foo;

// foo.cpp
#include "foo.h"
unsigned char foo_data[] = {0xde, 0xad, 0xbe, 0xef};
StaticData<const unsigned char> foo(foo_data, sizeof(foo_data));

这将隐藏实际数据,因为它仅在源文件中可见,并且访问它的唯一导出方法是通过 const 视图。