const、static and linkage
const
、static
修饰的variable都具备internal linkage。这是因为:
const
、static
所修饰的variable都是compile-time的,它们的value在compile-time就已经已知;在一个translation unit中,通过extern声明了一个variable,显然在compile-time是无法获知它的value的,显然,这是矛盾的,所以需要将它们的linkage指定为internal了;
下面是参考内容:
const
and linkage
下面是我改写How do I use arrays in C++?的5.1 Pitfall: Trusting type-unsafe linking.中的例子:
// [main.cpp]
#include <iostream>
extern const int length;
extern int* numbers;
void print_array();
int main()
{
print_array();
using namespace std;
std::cout << numbers << std::endl;
for (int i = 0; i < length; ++i)
{
cout << (i > 0 ? ", " : "") << (numbers + i * sizeof(int));
}
cout << endl;
}
// [numbers.cpp]
#include <iostream>
const int length = 9;
int numbers[length] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
void print_array()
{
std::cout << numbers << std::endl;
for (int i = 0; i < length; ++i)
{
std::cout << numbers + i << std::endl;
std::cout << numbers[i] << std::endl;
}
}
编译: g++ main.cpp numbers.cpp -g -o main
,报错如下:
/tmp/ccH5XSWb.o:在函数‘main’中:
/home/ust/main.cpp:13:对‘length’未定义的引用
collect2: 错误:ld 返回 1
上述问题,让我思考:const
和extern
。Google “extern const undefined reference c++”,下面是正解:
stackoverflow Why does “extern const int n;” not work as expected?
It's because const
implies internal linkage by default, so your "definition" isn't visible outside of the translation unit where it appears.
In this case, by far the best solution is to put the declaration (extern int const n;
) in a header file, and include that in both a.cpp
and b.cpp
. The linkage is determined by the first declaration the compiler sees, so the later definition in a.cpp
will have the correct (external) linkage.
Alternatively, you can force the linkage in the definition:
extern int const n = 8;
Despite the extern
, this is still a definition; anything with an initializer outside of a class definition is a definition.
const
and constexpr
variables in C++ have internal linkage (and thus aren't accessible in other compilation unit) if they aren't also declared extern
(either in the definition or in a previous declaration).
In C, it isn't the case (well C hasn't constexpr
) so your code is valid, and more you can put extern
on a definition.
So if you want to write code which is both C and C++ (and the two declarations should probably come from the same header as James pointed out):
// a.cpp
extern const int n;
const int n = 8;
// b.cpp
extern const int n;
int main()
{
int m = n;
}
if you don't
// a.cpp
extern const int n = 8;
is also possible
stackoverflow Mixing extern and const
- Yes, you can use them together.
- And yes, it should exactly match the declaration in the translation unit it's actually declared in. Unless of course you are participating in the Underhanded C Programming Contest :-)
The usual pattern is:
- file.h:
extern const int a_global_var;
- file.c:
#include "file.h"
const int a_global_var = /* some const expression */;
constexpr and linkage
这是c++11中引入的,那么它是否和const
一样,是internal linkage呢?
参考:
Example
在头文件BussinessTypes.h
中,如下定义
namespace BussinessTypes
{
int StockOpt = 1;
}
这种写法是非常不好的,当多个source file包含BussinessTypes.h
,则会出现:multiple definition of StockOpt
。
这让我想起来在头文件中声明的const
常量不会出现这种问题,则将上述修改为
namespace BussinessTypes
{
const int StockOpt = 1;
}
可以避免上述问题
这让我想起了const
的linkage,显然它是internal linkage的。