为什么重新定义固定大小的静态数组是必需的/有效的
Why is redefining a fix sized static array required/works?
我希望你们中的一个人能向我解释为什么编译器要求我在编译单元中重新定义一个静态固定长度数组,尽管我已经在头中这样做了。这里有一个例子:
MyClass.h:
#ifndef MYCLASS_H
#define MYCLASS_H
class MyClass {
private:
static char myPrecomputeTable[256];
}
#endif
MyClass.cpp
#include "MyClass.h"
char MyClass::myPrecomputeTable[256];
如果我删除MyClass.cpp中的重新定义,链接器会抱怨myPrecomputeTable未定义。语法似乎是多余的。有人能向我解释一下为什么编译器/链接器需要这个定义吗?
编辑:
对不起,我想我不清楚我困惑的是什么。我理解声明/定义的概念,更有趣的是定义数组的大小。在定义和声明中,我都必须定义似乎多余的大小。
编辑:
我做了更多的挖掘,发现这个主题的许多方法都是编译器友好的。编译:
MyClass.h
class MyClass {
static char myPrecomputeTable[256];
};
MyClass.cpp
char MyClass::myPrecomputeTable[256];
编译:
MyClass.h
class MyClass {
static char myPrecomputeTable[];
};
MyClass.cpp
char MyClass::myPrecomputeTable[256];
编译:
MyClass.h
class MyClass {
static char myPrecomputeTable[256];
};
MyClass.cpp
char MyClass::myPrecomputeTable[];
不编译:
MyClass.h
class MyClass {
static char myPrecomputeTable[512];
};
MyClass.cpp
char MyClass::myPrecomputeTable[256];
大小必须在标头或类中定义,或者同时在两者中定义,但编译器足够聪明,可以停止大小冲突。
在标题中:
class MyClass {
private:
static char myPrecomputeTable[256];
}
这是一个声明。
在.cpp中:
char MyClass::myPrecomputeTable[256];
是定义。
声明提供符号的基本属性:其类型和名称。
定义提供了该符号的所有细节——如果它是一个函数,它会做什么;如果它是一个类,它有哪些字段和方法;如果它是一个变量,那么该变量存储在哪里。
通常,编译器只需要有一个声明就可以将文件编译为对象文件,期望链接器可以从另一个文件中找到定义。如果没有源文件定义过一个符号,但它是声明的,那么在链接时您将收到抱怨未定义符号的错误。
一个很好的链接来理解两者之间的区别:http://www.cprogramming.com/declare_vs_define.html
来自标准:
3.1声明和定义[basic.def]
声明可以将一个或多个名称引入翻译单元,也可以重新声明以前声明引入的名称。如果是,则声明指定这些名称的解释和属性。声明也可能具有以下效果:
- 静态断言(第7条)
- 控制模板实例化(14.7.2)
- 属性的使用(第7条),以及
- 什么都没有(在空声明的情况下)
声明是定义,除非它在不指定函数体的情况下声明函数,它包含
extern
说明符或链接规范且既不是初始值设定项也不是function-body;它在类定义中声明静态数据成员,或者它是typedef声明、using声明ttribute声明空声明用指令。
头文件中的第一个只是一个声明,告诉编译器该成员存在于包括头文件的所有其他源文件中。
源文件中的第二个是实际的定义,链接器在将整个项目链接到单个可执行文件时需要它。
在必须告诉编译器两次大小的情况下,这就是指定语言的工作方式。你(或任何人)对此无能为力。
但是,您可以使用typedef
来解决它:
class MyClass
{
typedef char PrecomputeTable_t[256];
static PrecomputeTable_t myPrecomputeTable;
};
...
MyClass::PrecomputeTable_t MyClass::myPrecomputeTable;
- C++17中函数模板中的静态数组初始化(MSVC 2019)
- 静态数组的自由动态数组
- 如何在C++函数中声明静态 2D 数组?
- 从另一个静态常量数组初始化静态常量数组(只需少量计算)
- 基于字节数组生成静态范围整数值
- 如何在C++中删除静态数组?
- 为什么 &a 和 c++ 中的静态数组相同?
- 为什么静态数组成员变量在调用对象的实例后不显示任何内容?
- C++ 返回指向函数内定义的静态数组的指针是否有效?
- 将在堆栈上声明的元素添加到静态数组
- const_cast静态数组以添加恒常性
- C++访问静态 constexpr 数组
- 初始化类中的静态 const 数组 - C++
- 将静态字符数组中的字符分配给动态分配的字符数组 - 访问冲突
- 动态分配的数组和静态数组之间的区别
- 如何在 C++ 中使用 NULL(或 0)初始化静态字符数组
- C++编译时使用 constexpr 字符数组指针分配静态数组?
- 我可以使用 constexpr 函数声明一个静态数组吗?
- 如何在静态函数中使用成员函数数组
- 具有大的2d数组:静态int与int