如何声明和初始化一个作为类成员的静态常量数组?

32

非常容易理解。数组是一个整数类型,其内容已知且不可更改,并且不允许使用C++0x。它还需要声明为指针。我似乎找不到适用的语法。

在Class.hpp中的声明:

static const unsigned char* Msg;

Class.cpp里的东西是我一直在修改的:

const unsigned char Class::Msg[2] = {0x00, 0x01}; // (type mismatch)
const unsigned char* Class::Msg = new unsigned char[]{0x00, 0x01}; // (no C++0x)

...等等。我还尝试在构造函数中初始化,但显然这是不行的,因为它是一个常量。我所要求的是否不可能实现?


6
数组会衰变为指针,所以数组声明没问题吗? - chris
2
这不奇怪,存在类型不匹配问题。您混淆了数组和指针。 - user195488
1
@ACK_stoverflow,任何非引用数组传递到函数中都会被转换为指针,因此声明一个数组并将其传递到期望指针的函数中是可以正常工作的。 - chris
@chris 或许是因为我正在使用 --pedantic gcc 标志所以才会出现问题?不管怎样,这段代码需要非常干净,我的编译器也会对此发出警告。 - ACK_stoverflow
1
@ACK_stoverflow,这个在使用-pedantic编译时完全正常,并将一个数组传递到一个接受指针的函数中。 - chris
显示剩余6条评论
2个回答

51
// in foo.h
class Foo {
    static const unsigned char* Msg;
};

// in foo.cpp
static const unsigned char Foo_Msg_data[] = {0x00,0x01};
const unsigned char* Foo::Msg = Foo_Msg_data;

4
使用指针的解决方案,却避免了内存管理的麻烦,值得点赞。 - David Rodríguez - dribeas
为什么头文件中的声明必须是静态的? - RAAC
@RAAC因为你需要它是静态的,这样就可以在不实例化类对象的情况下访问它。 - Anubis
1
定义中不应该有 static 限定符吗?gcc 4.9.2 告诉我从 foo.cpp 中删除它。 - Peter Mitrano
这仍然比将静态数组作为类成员具有额外的间接层次。:(聪明的编译器可能会看穿它,而不是从Msg加载数组基地址(直接使用链接时常量Foo_Msg_data),但它并不完美。 - Peter Cordes
显示剩余2条评论

31

你正在混淆指针和数组。如果你想要一个数组,那么请使用一个数组:

struct test {
   static int data[10];        // array, not pointer!
};
int test::data[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

如果您需要一个指针,最简单的解决方案是在定义该成员的翻译单元中编写一个帮助函数:

struct test {
   static int *data;
};
// cpp
static int* generate_data() {            // static here is "internal linkage"
   int * p = new int[10];
   for ( int i = 0; i < 10; ++i ) p[i] = 10*i;
   return p;
}
int *test::data = generate_data();

2
+1 的混淆可能在于您可以以“类似数组”的方式访问 char* 的成员。 - user195488
抱歉,我应该更明确一些:我需要的是一个指向数组的常量指针。 - ACK_stoverflow
如果在编译时已知大小,为什么要动态分配内存?数组可以是静态的,并且仍然可以在运行时使用循环进行初始化(而不是将位表作为可执行文件的一部分)。这使得编译器能够通过删除额外的间接级别来进行优化,当它可以看到指针赋值时(就像其他答案建议的那样)。 - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接