静态 std::map 成员变量在 C++ 中安全吗?

问题描述 投票:0回答:1

假设我想实现一种查找表作为

std::map<std::string, int>
,例如:

// Utils.hpp header

class Utils
{
public:
    static std::map<std::string, int> NameToId;
   
    static int GetIdForName(const std::string & name)
    {
        auto it = NameToId.find(name);
        if (it != NameToId.end())
            return it->second;
        else
            return -1; // not found
    }
};

对应的.cpp文件中:

// Utils.cpp

#include “Utils.hpp”

std::map<std::string, int> Utils::NameToId = {
    {“foo”, 10},
    {“bar”, 20},
    …
};

有这样一个

static std::map
成员变量安全吗?

这是否会因

std::map
(和
std::string
动态初始化而导致细微的错误?

c++ static stdmap
1个回答
0
投票

这是我在 redis 客户端中修复的一个错误

客户端类可以创建订阅者对象(您需要一个客户端对象来创建订阅者):

class Client {

public:

  Subscriber subscriber() { ... }
};

订阅者包含这样一个(无序但相同的)静态映射:

class Subscriber {
public: 
  static std::map<...> table; 
}

现在,当您将两件事结合起来时,乐趣就开始了:

  1. 创建一个静态全局客户端(我并没有说遵循最佳实践会发生错误)
  2. 确保
    Client
    类的方法使用
    Subscriber::table
    进行一些查找(因为我们不喜欢
    switch
    if else
    )。好吧,实际上它使用了
    Subscriber
    的静态方法,并且使用了静态成员,但无论如何......

按照初始化-销毁的顺序,你拥有的是

  1. 创建客户端
  2. 创建订阅者
  3. 销毁订阅者
  4. 销毁客户端

就在步骤 3 和 4 之间,客户端可能有一些未处理的消息队列,当它开始处理它们时,它将必须使用死对象的静态属性。在所有那些死去的物体中。客户端和静态成员都位于全局空间中,我们只是碰巧在另一个静态成员之前初始化了客户端。

将其与客户端可能有多个并行操作的订阅者的事实混合在一起(公平地说,有一个线程正在运行,直到处理完内容 - 因此客户端对象必须在析构函数完成之前处理剩余数据),并且您有一个这是让你对消毒剂报告失去理智的好方法。享受

© www.soinside.com 2019 - 2024. All rights reserved.