不需要内存空间的c++零大小数组
C++ zero-size array that requires no memory space?
当声明模板化类的成员变量时,是否有一种方法可以根据某些模板参数的值使其需要零内存?
一个例子是定义像std::array<T,n>
这样的东西,当n==0
。
template<int num_optional_args> class C {
int some_variable;
std::array<int,num_optional_args> optional_args;
};
是否有办法消除开销的optional_args当num_optional_args==0
?
大多数std::array<T,n>
实现为一个T
元素保留空间,即使n==0
.
是否有另一种方法可以保留零空间?为什么这不是c++标准的一部分?
您可以专门化您的类型,以便当数字为0时optional_args
不存在。如果你需要对象存在,那么对象可以存在并被引用而实际上不占用空间的唯一方法是通过空基类优化。
你可以这样使用:
template<int num_optional_args>
class optional_args {
std::array<int,num_optional_args> args
public:
// whatever interface you want for the optional args.
void foo(int n) {
if (n < num_optional_args)
args[n];
throw std::runtime_error("out of range");
}
};
template<>
class optional_args<0> {
public:
// whatever interface you want for the optional args, specialized for 0 args.
void foo(int n) {
throw std::runtime_error("out of range");
}
};
template<int num_optional_args>
class C : optional_args<num_optional_args> {
int some_variable;
void bar() {
for (int i=0; i<num_optional_args; ++i) {
optional_args::foo(i);
}
}
};
您要么需要为至少一个元素保留空间,要么保留指向该元素的指针。不可能存在占用 0 内存的数组结构。
下面的结构体在创建时只接受一个int和一个指针,这几乎是接近于0的:
template<typename T>
class array {
int sz;
T *head;
};
除此之外,在类定义中要求零空间的概念是愚蠢的。希望它在实例化时占用接近零的空间可能是有意义的,并且可以通过如下方式参数化构造函数来实现:
template<typename T>
class array {
int sz;
T *head;
array(int n) {
if (n == 0) return;
head = new T[n];
}
};
正如禁卫军所说,你可以专精0。如果你想让类C的所有变体都有相同的接口,你可以让所有的C都从C<0>派生,像这样:模板类C;
template <> class C<0> {
int s;
public:
int blah();
};
template <int N> class C : public C<0>{
int a[N];
};
int C<0>::blah() {return s;}
int main() {
C<1> a;
C<0> b;
a.blah();
b.blah();
return 0;
}
如果您不关心您的东西的pod性,您可以使用Boost。CompressedPair:
template<int num_optional_args> class C {
boost::compressed_pair<int, std::array<int,num_optional_args>> data;
int& some_variable() { return data.first(); }
std::array<int,num_optional_args>& optional_args() { return data.second(); }
};
如果std::array是一个空类,这应该可以消除开销。但是您的类不再是POD,因为compressed_pair不是。
我真的不记得它在c++中是否完全合法,但我认为它仍然是在C中:你可以有一个零大小的数组,但它必须是结构定义的最后一个成员。历史上,它被用于可变长度缓冲区:
struct buffer
{
usigned int size;
byte data[0];
};
buf.data
是完全可用的数组指针,所以如果你注意malloc
N+sizeof(int)字节,那么你可以将其强制转换为buffer
,将size
设置为N,然后你就得到了一个带有size
前缀的N字节data
数组。关键是,每个这样的缓冲区将始终具有并以'size'前缀开始,然后具有数据,因此您可以将每个这样的缓冲区强制转换为buffer
并检查大小,然后使用*(data+x)或data[x]提供0
参见http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
然而,注意这是C,而不是c++,但我几乎肯定我在c++中也看到过这样的raw-mem技巧。
除此之外,最重要的一点是这样的数组将具有零字节长度。在上面的例子中sizeof(buffer) == sizeof(int),但仅当数组是最后一个成员时。如果您在数组之后添加另一个字段,那么数组和最后一个字段将需要具有不同的偏移量,因此零len数组最终将是1字节(+align),只是为了具有不同的地址。更不用说没有哪个编译器会允许你在结构体中间声明零len数组。它只能作为结构体的尾部- Mongodb c++驱动程序:如何查询元素的数组
- 将数组的地址分配给变量并删除
- 从C++本机插件更新Vector3数组
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 数组索引的值没有增加
- 将对象数组的引用传递给函数
- 为char数组调整zlib-zpipe
- 2D数组来自文本输入,中间有空格
- std::向量与传递值的动态数组
- 在c++中用vector填充一个简单的动态数组
- 使用strcpy将char数组的元素复制到另一个数组
- 声明后,gcc 的动态大小数组是否与标准数组有效相同?
- 将 int 数组转换为带有小数C++的双精度数组
- 如何将大括号初始值设定项用于动态大小数组和新数组?
- 对未知大小数组的引用的列表初始化:它是否应该推断数组大小?
- 返回指向固定大小数组C++的数组的指针
- 如何将小数数组转换为二进制数数组
- 对指向固定大小数组的指针数组的内存分配的解释
- 在 C++ 中创建固定大小的 int 数组的动态大小数组