不同翻译单元中的内联静态变量具有不同的值(c++17)

inline static variable in different translation units has different values(c++17)

我想实现一个包含全局变量的源文件,我想通过 inline static 来实现。我可以在翻译单元的上下文中更改变量(例如 i),但是当我在该翻译单元外部调用该变量时,调用者的结果将保持不变。就像每个单元都有一个副本。请参阅以下示例:

header.h

#ifndef UNTITLED1_TEST_H
#define UNTITLED1_TEST_H

namespace t {
    inline static int i{0};

    void inc() ;

    void print_i() ;
}

#endif //UNTITLED1_TEST_H

header.cpp

#include "header.h"

void t::inc() {
    t::i++;
}

void t::print_i() {
    std::cout << t::i << std::endl;
}

那么让我们看看程序是如何执行的:

main.cpp

#include "header.h"

int main() {
    t::inc();

    std::cout << t::i << std::endl; // -> output is: 0
    t::print_i(); // -> output is : 1
}

如您所见,变量i在不同的翻译单元中有不同的值,如何解决?我不能使用 类 或其他任何东西,因为客户需要这种格式的代码。

注意

我可以做下面的事情,但这不是主要问题,我想要一个全局变量:

t::i++; //instead of t::inc();
std::cout << t::i << std::endl; // it's okay now, but it's not what I wanted

或者,我可以使用 inline 而不是 inline static。它似乎有效,但我的导师说我应该改用 inline static

static 变量(如您的示例)具有 内部链接 。有两种方法可以实现您想要的效果,如下所示。另请注意,static 关键字还有其他含义。

方法一:C++17

在 C++17 中,我们可以使用 inline 关键字,如下所示:

header.h

#ifndef UNTITLED1_TEST_H
#define UNTITLED1_TEST_H

namespace t {
    inline int i{0};//note the keyword inline here and initializer while keyword static has been removed 

    void inc() ;

    void print_i() ;
}

#endif

header.cpp

#include "header.h"
#include <iostream>

//No need for initilaizing t::i here

void t::inc() {
    t::i++;
}

void t::print_i() {
    std::cout << t::i << std::endl;
}

main.cpp

#include <iostream>
#include"header.h"

int main() {
    t::inc();

    std::cout << t::i << std::endl; // -> output is: 1
    t::print_i(); // -> output is : 1
}

方法1的输出可见here.

方法二:Pre-C++17

这里我们使用extern关键字,这样变量就可以有外部链接.

main.cpp

#include <iostream>
#include"header.h"

int main() {
    t::inc();

    std::cout << t::i << std::endl; // -> output is: 1
    t::print_i(); // -> output is : 1
}

header.h

#ifndef UNTITLED1_TEST_H
#define UNTITLED1_TEST_H

namespace t {
    extern int i;//note the keyword extern and no initializer here

    void inc() ;

    void print_i() ;
}

#endif

注意我删除了添加的 staticinline 关键字,并添加了 extern 关键字。现在该变量具有 外部链接 。另外,请注意 t::i 的初始化是在下面给出的 header.cpp 中完成的。

header.cpp

#include "header.h"
#include <iostream>

int t::i{}; //initialize t::i

void t::inc() {
    t::i++;
}

void t::print_i() {
    std::cout << t::i << std::endl;
}

以上程序的输出为:Demo

1
1

此外,请注意关键字 static 还有其他含义。但是我已经根据给定的示例代码片段进行了回答。

关键字 static 有许多不同的含义,具体取决于上下文。您在错误的上下文中使用了 static。你可以这样做

namespace t {
     inline int i{0}; // no static
}

或这个

class t {
  public:
     inline static int i{0};
}:

所有这些都应该在头文件中,.cpp 文件中没有其他定义,也没有 extern 关键字。这些东西在 C++14 或更早版本中是必需的,但在 C++-17 或更高版本中不需要。