我可以内联使用静态变量的函数吗?

Nar*_*ann 5 c++ static-variables inline-functions

我有这个代码:

// my.h

#ifndef MY_HEADER
#define MY_HEADER

int create_uid();

#endif
Run Code Online (Sandbox Code Playgroud)
// my.cpp

#include "my.h"

static int _next_uid = 0;

int create_uid()
{
    return _next_uid++;
}
Run Code Online (Sandbox Code Playgroud)

我想内联create_uid(),同时保持_next_uid变量对程序全局,以便变量是唯一的。

我的问题是:

  1. 我可以这样做吗?
  2. inlinerequire 语句_next_uid在编译单元之外是否可见?

注意:似乎并没有清楚地回答这些问题。

Plu*_*eto -1

概括:

inline next_id()如果将 的实现放在单个c文件中,这意味着该函数位于单个编译单元中,则它不起作用。所以main找不到inline next_id(),你会得到错误undefined reference

inline next_id()如果在共享头文件中声明它就可以编译,在这种情况下每个编译单元都会正确找到inline next_id(),在这种情况下每个编译单元都会正确找到.

就我而言,该全局变量只有一个实例会出现在.DATA进程的虚拟地址空间段中。输出的数字是连续的。

例子:

生成文件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
Run Code Online (Sandbox Code Playgroud)

主要.cpp 12:

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
Run Code Online (Sandbox Code Playgroud)

第二个.hpp 1:

#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;
}
Run Code Online (Sandbox Code Playgroud)

第二个.cpp 7:

void consume_id();
Run Code Online (Sandbox Code Playgroud)

分享.hpp 4:

#include <cstdio>

#include "share.hpp"

void consume_id(){
    printf("[scnd] %d\n", next_id());
}
Run Code Online (Sandbox Code Playgroud)

分享.cpp 7:

#pragma once

int next_id();

Run Code Online (Sandbox Code Playgroud)

结果输出:

[main] 0
[scnd] 1
[main] 2
[scnd] 3
[main] 4
Run Code Online (Sandbox Code Playgroud)

但如果改成:

分享.cpp 4:


static int _next_id = 0;

int next_id()
{
    return _next_id++;
}
Run Code Online (Sandbox Code Playgroud)

对“next_id()”的未定义引用

如果改为

分享.hpp 7:

[main] 0
[scnd] 1
[main] 2
[scnd] 3
[main] 4
Run Code Online (Sandbox Code Playgroud)

作品

编辑

这似乎是一个未定义的行为

我正在使用 `gcc 版本 11.2.0 (Ubuntu 11.2.0-19ubuntu1)

就我而言

static int _next_id您将拥有但仅在目标文件中的副本。记忆里只有一个。

inline int next_id()
{
    return _next_id++;
}
Run Code Online (Sandbox Code Playgroud)

主要.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    
Run Code Online (Sandbox Code Playgroud)

这里的函数_Z7next_idv只在内存中出现1次。

主要.s 147:

    11bb:   8b 05 53 2e 00 00       mov    0x2e53(%rip),%eax        # 4014 <_ZL8_next_id>
Run Code Online (Sandbox Code Playgroud)

的标签_next_idis _ZL8_next_id,也只在内存中出现 1 次。

  • @DanielLangr你可能是对的,但仍然认为它是UB(但由于稍微不同的原因)。不是因为静态变量(具有内部链接),而是因为内联函数(具有外部链接)。内联函数需要在所有翻译单元中具有**相同的**定义。现在,由于函数声明引用了不同的静态“_next_id”实体,因此它们不再相同。不管怎样,如果我编译上面的程序并进行优化和不进行优化,我会得到不同的结果。这通常是 UB 的征兆。 (2认同)