【问题标题】:inline vs static for nonmember global variables非成员全局变量的内联与静态
【发布时间】:2021-09-15 12:27:48
【问题描述】:

假设我有一个 C++ 标头

utils.h

而且我想在多个 TU 中提供一些常量映射(映射不在一个类中,普通的全局变量/常量)。

const std::map<int, std::string> ToString{{1,"1"}, {2, "2"}};

我应该声明它是内联的还是静态的? 换句话说:

static const std::map<int, std::string> ToString{{1,"1"}, {2, "2"}};

或

inline const std::map<int, std::string> ToString{{1,"1"}, {2, "2"}};

(AFAIK 都可以防止 ODR 违规,通过使链接成为内部的静态,以及通过允许有多个定义来内联,但我可能是错的,我经常在 ODR 上犯错误)。

注意:我想避免使用extern 的解决方案。

【问题讨论】:

  • 您是否考虑过使用extern 链接声明它并在其中一个TU 中定义它?
  • 我确信inline 会起作用并且不会导致 ODR 违规。不太确定static
  • 我知道走静态路由会给每个 TU 一个对象的“副本”。因此,在一个 TU 中对其进行的更改不会反映在其他 TU 中。
  • @SamVarshavchik 我讨厌那个解决方案:),我会修改问题以提及我想避免 extern。
  • static 如果后面有 inline 函数引用该变量,则 ODR 也可能有问题。

标签: c++ c++17 inline one-definition-rule


【解决方案1】:

还有一个选择

// header file main.h

#pragma once

#include <map>
#include <string>

static const auto& get_string_map()
{
    static const std::map<int, std::string> ToString{ {1,"1"}, {2, "2"} };
    return ToString;
}

// implementation file main.cpp

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

int main()
{
    auto map = get_string_map();
    std::cout << map.at(1);
}

【讨论】:

  • 现在,问题是static 还是inline 函数?
  • auto map -> const auto&amp; map 或 auto&amp;&amp; map 以避免复制。
【解决方案2】:

好问题! AFAIK,您可以同时使用两者来实现您的目标:

// utils.h

#include <map>

static inline const std::map<int, std::string> ToString{{1,"1"}, {2, "2"}};
  • inline 提示编译器将包含此标头的所有文件合并到一个文件中,从而满足 ODR。注意:在 C++20 中,inline 只是为了便于阅读,如果它不会提高性能,编译器会忽略它。
  • static 强制 ToString 成为有助于提高性能的编译时值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-20
    • 2015-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多