在C/C++头文件中定义函数时使用static关键字的那些事

首先,如果在头文件中定义一个普通的函数,比如下面这样,肯定会在程序链接的时候报“重复定义”的错误。

// 错误的版本,链接时会报重复定义错误
void DoSomething()
{
}

D:/kexin/untitled5/s.h:16: multiple definition of `DoSomething()'
CMakeFiles\untitled5.dir/objects.a(1.cpp.obj):D:/kexin/untitled5/s.h:16: first defined here
collect2.exe: error: ld returned 1 exit status

那么如果我们想在头文件中定义一些常用的函数,一般做法是在函数前加“inline”关键字,这样就不会报“重复定义”的错误了,并且能够像函数一样被其他的c/cpp源码文件调用了。

// inline版本,没有问题
inline void DoSomething()
{
}

这时候如果你在inline后面加入“static”关键字也是没问题的:

// inline static版本,也是没有问题
inline static void DoSomething()
{
}

区别是:加了static关键字后,每个调用它的c/c++源码文件都会有一个copy,即static其实是限制了函数的作用域在本源码文件内。

----------------------------------- 分割线 ----------------------------------------
那么另一个问题来了:如果我们在函数内部定义static变量时,会是怎么样的情况呢?

// 版本1:非static的inline函数内部定义static变量
inline void NonStaticInlineFunc()
{
    static int localVar;
    std::cout << "In NonStaticInlineFunc: localVar = " << (void*)&localVar << std::endl;
}
// 版本2:static的inline函数内部定义static变量
inline static void StaticInlineFunc()
{
    static int localVar;
    std::cout << "In StaticInlineFunc: localVar = " << (void*)&localVar << std::endl;
}

如果我们分别在1.cpp和2.cpp两个源码文件中分别调用这两个inline函数,可以通过结果看到区别。

// 1.cpp
void foo1()
{
    std::cout << "Calling by foo1" << std::endl;
    NonStaticInlineFunc();
    StaticInlineFunc();
}
// 2.cpp
void foo2()
{
    std::cout << "Calling by foo2" << std::endl;
    NonStaticInlineFunc();
    StaticInlineFunc();
}

程序运行结果:

Calling by foo1
In NonStaticInlineFunc: localVar = 0x4040b0
In StaticInlineFunc: localVar = 0x408044
Calling by foo2
In NonStaticInlineFunc: localVar = 0x4040b0
In StaticInlineFunc: localVar = 0x408054

可以看到:如果在inline后加了static关键字,则在函数中定义的static变量则会在每一个源码调用文件中产生了一个拷贝,而没加static关键字的inline函数则会产生一个全局的static变量。

具体解释参考https://stackoverflow.com/questions/185624/static-variables-in-an-inlined-function

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 最近在学习 c++, 在编译与链接过程中遇到了一些定义与声明的问题, 经过多处查阅资料, 基本解惑. 现记录与此,...
    闪耀旅途阅读 853评论 0 1
  • 1 原理 1.1 首先,关于声明和定义的区别。 这种写法(函数原型后加;号表示结束的写法)只能叫函数声明而不能叫函...
    Pitfalls阅读 6,596评论 2 12
  • const: 所修饰的对象或变量不能改变,修饰函数时,该函数不能修改在函数外面声明的变量,也不能调用任何非cons...
    Catcola阅读 505评论 0 0
  • static关键字是C, C++中都存在的关键字, 它主要有三种使用方式, 其中前两种只指在C语言中使用, 第三种...
    王王王王王景阅读 303评论 0 0
  • 姓名:王重月 学号:21021211019 学院:电子工程学院 转自:(30条消息) 嵌入式面经_Oliver.H...
    宇智波大星阅读 459评论 0 0