C++在头文件中定义const变量或static变量

C++在头文件中定义const变量或static变量

问题引入

代码中总能看到有的人喜欢在头文件中定义const变量,或者在头文件中定义static变量。最常见的就是在头文件中定义字符串,例如在头文件def.h中定义变量:

// defs.h

static std::string s_str = "Static";

const std::string kStr = "Const";

这样写就可以在需要用到该字符串的地方引入这个头文件。

在源文件中引入头文件相当于直接把头文件的内容拷贝到原文件中,如果引入这个头文件后,将会在每个引入的源文件中重复定义这些变量。在C++中这样的代码是可以编译通过的,但是在C语言编译器中是不能编译通过的。

C编译器情况

如果在头文件中定义static变量,在多个源文件中引入是可以编译通过的,因为相当于在每个源文件中定义了一个static变量,而static变量的作用域限定在这个源文件内的。

如果在头文件中定义了const变量,在多个源文件中引入是不能编译通过的,因为const没有限定作用域,每个文件都定义这个变量,会出现重复定义的错误。如下:

fatal error LNK1169: one or more multiply defined symbols found

C++编译器情况

在C++的头文件定义const或static变量,引入到多个源文件都是可以编译通过的。但是导致也导致了重复定义变量的问题。

接下来用代码验证一下,在一个头文件中定义一个const变量,当引入到多个源文件中,查看该类的构造函数调用过几次,以及内存的变化情况。如果该头文件引入到3个文件中,那么该类的构造函数应该调用3次,内存也会明显增加。

1.头文件header.h

// header.h

#pragma once

#include

#include

struct LargeObject {

int* p;

LargeObject() {

p = new int[100000000];

std::cout << "Construct" << std::endl;

}

~LargeObject() {

delete p;

}

};

const LargeObject kLargeObject;

const std::string kStr = "string";

2.将header.h引入到Test1.cpp中。

// Test1.h

#pragma once

void Func1();

// Test1.cpp

#include "Test1.h"

#include "Header.h"

void Func1() {

// 输出kLargeObject 的地址。

std::cout << "Large Object : " << &kLargeObject << std::endl;

// 输出kStr 的地址。

std::cout << "String: " << &kStr << std::endl;

}

3.在main.cpp中输出内存。

#include

#include

#include

#include

#include "Test1.h"

#pragma comment(lib,"psapi.lib")

void ShowMemory() {

HANDLE handle = GetCurrentProcess();

PROCESS_MEMORY_COUNTERS pmc;

GetProcessMemoryInfo(handle, &pmc, sizeof(pmc));

std::cout << "Memory:" << pmc.WorkingSetSize / 1000 << "K" << std::endl;

}

int main() {

Func1();

std::cout << std::endl;

ShowMemory();

return 0;

}

输出结果为:

4.将header.h引入到Test2.cpp中。

// Test2.h

#pragma once

void Func2();

// Test2.cpp

#include "Test2.h"

#include "Header.h"

void Func2() {

// 输出kLargeObject 的地址。

std::cout << "Large Object : " << &kLargeObject << std::endl;

// 输出kStr 的地址。

std::cout << "String: " << &kStr << std::endl;

}

5.在main.cpp中输出内存。

#include

#include

#include

#include

#include "Test1.h"

#include "Test2.h"

#pragma comment(lib,"psapi.lib")

void ShowMemory() {

HANDLE handle = GetCurrentProcess();

PROCESS_MEMORY_COUNTERS pmc;

GetProcessMemoryInfo(handle, &pmc, sizeof(pmc));

std::cout << "Memory:" << pmc.WorkingSetSize / 1000 << "K" << std::endl;

}

int main() {

Func1();

Func2();

std::cout << std::endl;

ShowMemory();

return 0;

}

输出结果为:

结果对比:

结果2的内存明显大于结果1的内存。结果2中的构造函数调用了两次,因为该头文件引入了两次。结果2中输出的变量地址不同,说明是不同的变量。

结论

不要直接在头文件中定义const或static变量,更好的写法是在源文件中定义,在头文件中extern声明。例如:

// defs.h

extern const std::string kStr;

extern const Student kStu;

// defs.cpp

const std::string kStr = "String";

const Student kStu("Name");

🎈 相关推荐

Scala兴衰史:暂时的没落或许是一个新的开始
365体育亚洲官方登录

Scala兴衰史:暂时的没落或许是一个新的开始

📅 07-27 👀 8472
华为手机没有声音?快速解决方法全解析
beat365网站假的吗

华为手机没有声音?快速解决方法全解析

📅 07-27 👀 873
浅笑流年是什么意思 浅笑流年的解释
365体育亚洲官方登录

浅笑流年是什么意思 浅笑流年的解释

📅 08-02 👀 1945