摘要:
如果你将inline next_id()
的实现放在单个c
文件中,即该函数在单个编译单元中,则它将无法工作。因此,main
找不到inline next_id()
,会出现undefined reference
错误。
如果你在一个共享头文件中声明inline next_id()
,则可以编译它,这样每个编译单元都能正确找到inline next_id()
。
在我的情况下,在进程的虚拟地址空间的.DATA
段中,只有一个全局变量的实例。输出的数字是连续的。
示例:
Makefile 8:
all:
c++ -c main.cpp
c++ -c second.cpp
c++ -c share.cpp
c++ main.o second.o share.o -o main
clean:
rm -f main.o second.o share.o main
main.cpp 12:
#include <cstdio>
#include "share.hpp"
#include "second.hpp"
int main(){
printf("[main] %d\n", next_id());
consume_id();
printf("[main] %d\n", next_id());
consume_id();
printf("[main] %d\n", next_id());
return 0;
}
second.hpp 1:
void consume_id();
second.cpp 7:
#include <cstdio>
#include "share.hpp"
void consume_id(){
printf("[scnd] %d\n", next_id());
}
share.hpp 4:
#pragma once
int next_id();
share.cpp 7:
static int _next_id = 0;
int next_id()
{
return _next_id++;
}
结果输出:
[main] 0
[scnd] 1
[main] 2
[scnd] 3
[main] 4
但如果它被改成:
share.cpp 4:
inline int next_id()
{
return _next_id++;
}
未定义对 `next_id()' 的引用
如果更改为
share.hpp 7:
#pragma once
static int _next_id = 0;
inline int next_id()
{
return _next_id++;
}
工作
编辑:
似乎是未定义的行为
我正在使用 `gcc 版本 11.2.0(Ubuntu 11.2.0-19ubuntu1)
在我的情况下
您将拥有 static int _next_id
的副本,但仅在对象文件中。在内存中只有一个。
objdump -d main > main.s
main.s 143:
00000000000011b3 <_Z7next_idv>:
11b3: f3 0f 1e fa endbr64
11b7: 55 push %rbp
11b8: 48 89 e5 mov %rsp,%rbp
11bb: 8b 05 53 2e 00 00 mov 0x2e53(%rip),%eax # 4014 <_ZL8_next_id>
11c1: 8d 50 01 lea 0x1(%rax),%edx
11c4: 89 15 4a 2e 00 00 mov %edx,0x2e4a(%rip) # 4014 <_ZL8_next_id>
11ca: 5d pop %rbp
11cb: c3 ret
这里的函数_Z7next_idv
只在内存中出现了1次。
main.s 147:
11bb: 8b 05 53 2e 00 00 mov 0x2e53(%rip),%eax # 4014 <_ZL8_next_id>
_next_id
的标签是 _ZL8_next_id
,在内存中也只出现了1次。
_next_uid
是全局命名空间范围内的保留标识符,因为它以下划线开头。您不允许在那里声明它。 - user17732522inline
,那个函数只能在一个翻译单元中定义,这意味着编译器无法将其代码内联到其他翻译单元中。 - Daniel Langr