探讨下c++的声明和定义问题,关于extern

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了探讨下c++的声明和定义问题,关于extern相关的知识,希望对你有一定的参考价值。

c++primer第四版中,53页的习题2.18中问到,
extern std::string name;是属于声明还是定义?
答案说的是声明。
不过我认为,string类中有默认构造函数,如果该语句在函数外,那么则会自动获得储存空间,将name定义为空字符串,不知各位有何高见?
感谢回答我的关于extern的问题,可是还是没想通。正如一楼举的例子extern std:tring name("Zhang3Li4");我认为extern std::string name;和那句是一样的 .因为标准库中的string是有默认构造函数的,若后面什么都没有的话,就初始为空字符串

我刚才做了一个实验:
//a.cpp
#include <string>

std::string i;

//b.cpp
#include <iostream>
#include <string>

extern std::string i;

int main ()

std::cout << i << std::endl;


运行结果为:

(上面是一空行:由于末尾用了endl)

如果没有a.cpp这个文件,运行出错
这是一对实验(有没有a.cpp文件)

可得出这样的结论:
a.cpp中std::string i;是定义(本来就是)
b.cpp中extern std::string i; 则是声明(你的问题)

先别急,这只是实验结果。我们还需要理论依据,那么下面就试着解释一下:

下面是另一个例子(也是第二个实验)
你应该知道内置类型(int等)如果作为全局变量时,定义的同时也就初始化了(一个内置类型有其对应的默认值;如果你将自定义类型也看成内置类型,那么就等于说,一个自定义类型有其对应的默认值(由默认构造函数完成))。如
//c.cpp
int i;

//d.cpp
#include <iostream>

extern int i;

int main ()

std::cout << i << std::endl;


那么在这里int i; 就是定义(并且初始化了i,初始值为0)
因而输出结果为
0
//这个实验的运行结果符合理论依据。
(我使用的编译器是visual studio 2008)

从这两个实验来看:(将两个“默认”等同起来)
int i;
std::string i;
都可以作为初始化i的定义性语句。
那么
extern int i;
extern std::string i;
也具有定义行为(这个很明显与extern的用法相悖)

在以上两个试验中:int 与 string 有“区别”吗?所有的代码都一样只不过把std::string 换成了 int而已!如果你能解释int的情况,那么我想std::string问题也就迎刃而解了!

于是我个人总结出一个结论:
不论是内置类型还是自定义类型,前面有extern关键字,如果没有显式地初始化参数(即就是自定义类型的默认构造函数被extern屏蔽了,不起初始化的作用),那么就按声明对待。

可能我的描述很混乱,希望你好好看看上面的例子,就明白了!
注意:从这里可以看出来默认构造函数的特殊性!
参考技术A string 实际上是:
typedef basic_string<char> string;

extern std::string name; 属于声明

如果是 extern std::string name("Zhang3Li4"); 另当别论。

extern 相当声明为 全局量 (外部于本程序块)。

C++静态成员变量必须在类的定义之外进行声明 (error LNK2001: unresolved external symbol)


文章目录

小结

C++的Visual Studio工程返回error LNK2001的错误,以及在调试运行的过程中出现了Unhandled exception (ntdll.dll)的问题,对这两个问题进行了解决。

问题和解决

Error LNK2001错误

参考描述:
​​​non-const data members should be defined outside of the class definition and inside the namespace enclosing the class. The usual practice is to define it in the translation unit (*.cpp) because it is considered to be an implementation detail. ​

也就是非静态数据成员应该定义在类的外面,需要在调用这个类的命名空间之内进行一次定义声明。 通常的做法是的把这个非静态数据成员定义在C++程序文件(*.cpp)中。

例如在一个并文件中(*.h),有一个类中定义了如下静态成员变量:

static RosbridgeWsClient rosBridgeConn;

那么需要在相应的*.cpp中定义声明这个静态成员变量。否则会报错:
​​​LNK2001 unresolved external symbol "private: static class......​

具体解决问题的定义方法如下:

RosbridgeWsClient RoboticArmJetmax::rosBridgeConn("xxx.xx.xx.xx:9090");

修改后测试通过没问题。

Unhandled exception (ntdll.dll)

在程序运行的过程中会报错:​​Unhandled exception at 0xxcxxxxxxx (ntdll.dll) in xxx.exe: 0x12345678: Access violation writing location 0x-xxxxxxxx​

具体的问题可能是使用的库的问题,参考:​​Unhandled exception at 0x77081d76 (ntdll.dll) in Stereo Vision.exe: 0xC0000005: Access violation writing location 0x00000014​

​工程属性-> C/C++ -> Code Generation -> Run Time Library -> Multi-threaded Debug DLL (/MDd)​

进行了修改后再也没出现过这个问题了。

参考

​C++类静态成员变量导致报错error LNK2001: unresolved external symbol "private: static class​​​​Stackoverflow: error LNK2001: unresolved external symbol "private: static class​​​​Unhandled exception at 0x77081d76 (ntdll.dll) in Stereo Vision.exe: 0xC0000005: Access violation writing location 0x00000014​


以上是关于探讨下c++的声明和定义问题,关于extern的主要内容,如果未能解决你的问题,请参考以下文章

(C++) 如何将 stl 列表声明为 extern?

关于存储持续性,作用域,链接性,static与extern

C++中的声明和定义

转自简书:关于FOUNDATION_EXTERNexternFOUNDATION_EXPORTextern "C"的区别

关于C++ extern的简单总结

C++中如何定义变量