为何对静态数组typemap_使用sizeof()会触发C2070编译错误?
sizeof(typemap_)会触发编译错误? 这个问题其实是C++里关于不完整类型和静态成员数组声明/定义分离的典型坑,我来给你拆解清楚:
核心原因:类内声明的数组是「不完整类型」
你在类内部的声明是:
static std::pair<const Type, const size_t> typemap_[];
这里只声明了数组的存在,但没有指定它的大小——在C++里,这种写法属于不完整类型(incomplete type)。而sizeof运算符的操作数必须是完整类型(编译器能确定其大小的类型),所以直接对typemap_用sizeof时,编译器会报错“sizeof操作数非法”,因为它此时不知道这个数组到底有多少个元素。
而sizeof(typemap_[0])是合法的,因为不管数组是不是完整类型,typemap_[0]的类型是明确的(std::pair<const talos::Message::Type, const size_t>),编译器可以直接计算单个元素的大小,不需要知道数组的总长度。
为什么外部定义了大小还是不行?
你在类外部的定义:
std::pair<const talos::Message::Type, const size_t> talos::Message::typemap_[8] = { ... };
确实给数组指定了大小,但这个定义是类外部的实体定义。在你使用sizeof(typemap_)的代码位置,如果编译器还没看到这个完整的定义(比如代码顺序是先调用sizeof,后出现数组定义;或者sizeof的调用在类的成员函数里,而成员函数的实现放在头文件中,没链接到数组定义的编译单元),那么编译器仍然会把typemap_当作不完整类型处理,自然无法计算它的总大小。
怎么解决这个问题?
有几种常见的解决方案:
在类内声明时直接指定数组大小:
把类内的声明改成:static std::pair<const Type, const size_t> typemap_[8];这样编译器在类作用域里就知道数组是完整类型了,任何地方调用
sizeof(typemap_)都能直接计算出8 * sizeof(typemap_[0])。用静态成员函数返回数组大小:
如果不想在类内硬编码大小,可以写一个静态成员函数,在类外部定义它(此时能看到数组的完整定义):// 类内声明 static size_t get_typemap_size(); // 类外部定义 size_t talos::Message::get_typemap_size() { return sizeof(typemap_); }之后调用
get_typemap_size()就能拿到数组的总大小,避免直接对不完整类型用sizeof。C++17及以后用
inline静态数组:
可以把数组的声明和定义合并在类内(需要C++17或更高版本):static inline std::pair<const Type, const size_t> typemap_[] = { { talos::Message::Type::Empty, typeid(int).hash_code() }, { talos::Message::Type::Keyboard , typeid(int).hash_code() }, // ... 其他元素 };这样数组是完整类型,
sizeof(typemap_)可以直接使用,还避免了多编译单元重复定义的问题。
内容的提问来源于stack exchange,提问作者Mathis

