g++ 链接 变量被多次定义?
这是map_test.h文件
#ifndef _MAP_TEST_H
#define _MAP_TEST_H
#include <map>
#include <string>
using std::map;
using std::string;
map<string, string> map_config;
void init_map_config();
#endif
这是map_test.cpp文件
#include "map_test.h"
void init_map_config()
{
map_config.insert({"123", "123"});
map_config.insert({"456", "456"});
map_config.insert({"789", "789"});
}
这是main.cpp文件
#include <iostream>
#include "map_test.h"
using std::cout;
using std::endl;
int main()
{
init_map_config();
for (auto it = map_config.begin(); it != map_config.end(); it++)
cout << it->first << " " << it->second << endl;
cout << endl;
}
编译:
g++ -c map_test.cpp -o map.o -std=c++11
g++ -c main.cpp -o main.o -std=c++11
编译都是成功的,链接过程出错:
g++ map.o main.o -o main
此时出错:
main_test.o:(.bss+0x0): `map_config'被多次定义
map_test.o:(.bss+0x0):第一次在此定义
collect2: error: ld returned 1 exit status
为什么会报错?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
因为违背了ODR。map_config定义在头文件中,并且是外部链接。这个头文件分别被两个源文件包含,这导致链接时map_config在两个目标文件中有定义。
解决方案是将定义移到源文件中,在头文件中只留下纯声明。
1,在
map_test.cpp
文件中定义map<string, string> map_config;
2,在
map_test.h
中使用extern map<string, string> map_config;
变量和函数的定义 , 都应该放在cpp文件中, 否则很容易产生多重定义.
为什么呢?
因为c++的编译单位是cpp文件. 如果这个头文件被多个cpp包含了, 那么这个头文件中的定义的变量或者 函数就会在这些cpp生成的obj中存在, 在链接的时候, 就会发现多个obj存在同一个变量或者函数实现, 自然就会报重定义了.
所以:
除非你能清楚的知道, 这个头文件只会被一个cpp文件包含一次. 那么放到头文件中没有问题.
如果不确定, 那么变量定义或者函数的实现, 就老实的放到.cpp文件中吧.
可能你要问, 变量放到.cpp中的, 那么其它文件中如何使用它呢?
答案是使用声明: extern
比如: extern map<string, string> map_config;
有两种解决办法
在头文件中使用extern声明,在源文件中定义
将map<string, string> map_config和函数init_map_config都定义为static