公平警告,我是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
变量。
答案 0 :(得分:2)
从全局内存中消除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;
}
答案 1 :(得分:1)
那么您正在寻找的是对任意数据的const视图,其中数据本身是私有的?也许是这样的事情:
// 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视图。