如何在运行时以最小的开销共享全局常量?

时间:2019-04-03 15:21:41

标签: c++ c++11

我正在使用C ++ 11。我不允许使用boost等外部库。只能使用STL。

我有很多事件,必须将其标识为字符串常量。我不允许使用枚举或整数或任何其他数据类型。例如:

  

“ event_name1”

     

“ event_name2”

     

“ some_other_event_name3”

     

“ a_different_event_name12”

然后,我有一些需要使用这些字符串的类,但不知道其他类是否存在(它们之间没有任何关系)。

class Panel{

    void postEvent(){
        SomeSingleton::postEvent("event_name");
    }
}

另一堂课::

class SomeClass{

    SomeClass(){
        SomeSingleton::listenForEvent("event_name");
    }

    void receiveEvent(){
         //This function is triggered when "event_name" occurs.
         //Do stuff
    }
}

所有这些事件都是常量,用于标识正在发生的事情。

这是我尝试过的:

How to store string constants that will be accessed by a number of different classes?

那里的一些人建议我提供有关如何解决具体问题的具体细节,因此我创建了这个新问题。

如何将字符串存储在公共文件中,以便使用这些字符串的所有其他类都可以引用同一文件?

  • 我不想在应用程序的生命周期内浪费内存或泄漏内存(它是移动应用程序)
  • 编译时间对我来说并不重要,因为该项目规模不大
  • 预计可能会有50个不同的事件。
  • 似乎将所有字符串保存在一个文件中,并在情况发生变化时仅编辑该文件会更易于维护。
  • 任何班级都可以随时监听任何事件,在编译之前我不会知道

5 个答案:

答案 0 :(得分:8)

最简单的方法是使用一个char const*常量,因为它更易于优化并且不使用动态分配。

您还可以在std::string_view函数中使用postEvent,避免动态分配。此步骤是可选的。如果您无法使用字符串视图,但仍然希望避免动态分配,请参考实现的SSO最大容量,并让事件名称保持在该大小以下。

还要考虑nonstd::string_view可以作为C ++ 11库提供,并且很可能是您需要的抽象。 cpp17_headersstring-view-lite之类的库仅用于此目的。

它看起来像这样:

constexpr auto event_name1 = "event_name1";

在类中作为静态成员,其工作方式相同:

struct Type {
    static constexpr auto event_name1 = "event_name1";
};

这最多将占用可执行文件的只读静态数据中的空间。

答案 1 :(得分:4)

鉴于您仍然使用C ++ 11,我认为来自here的建议仍然有效:

#ifndef INCLUDED_EVENT_NAMES
#define INCLUDED_EVENT_NAMES

#pragma once

namespace event_names
{
    constexpr auto& event_1 = "event_1";
    constexpr auto& event_2 = "event_2";
}

#endif

定义对字符串文字对象的命名引用非常简单,不需要任何其他库,保证不会引入任何不必要的对象,在您静态分配的字符串文字对象的存储上不需要任何额外的内存仍然需要,并且不会有任何运行时开销。

如果可以使用C ++ 17,我建议您使用std::string_view方法,但是在C ++ 11中,我认为以上内容很可能是您的应用程序的一个不错的折衷方案。 / p>

答案 2 :(得分:3)

全局const std::string有一个缺点,它需要在启动期间进行处理并创建字符串文字的副本。

链接的SO answear使用constexpr std::string_view,这是一个很酷的解决方案,因为构造函数是constexpr,因此启动时无需执行任何操作。此外,它不会创建任何副本。问题是这是C ++ 17

使用const char [](或autoconstexpr)是一种久经考验的解决方案。您可以将std::string与它进行比较,而不会产生任何额外开销。

您可以为所有字符串创建头文件,并让链接程序删除所有重复项。它的工作方式与旧的C ++一样。

答案 3 :(得分:2)

您可以使用静态字符串的结构:

struct MyNames
{
    static const std::string name1;
};

在cpp中:

const std::string MyNames::name1 = "foo";

然后可以从所有必需的位置访问名称。在C ++ 17中,应该使用string_view来避免对象构造。但这基本上是该答案的重复,基本上是:https://stackoverflow.com/a/55493109/2266772

答案 4 :(得分:1)

为了适当的抽象和良好的设计,您应该定义事件类。该事件类将具有:

  • 提供字符串(例如name()system_name())的方法
  • 转换为字符串的运算符(不推荐)
  • 发生这种事件的to_string()独立式功能(不推荐)

但是除此之外,您所有的类现在都可以使用枚举,索引或它们喜欢的任何东西了,只要它们与任何东西交互,就只需要使用转换方法即可。需要字符串。因此,您的任何类都不必真正了解那些字符串本身。

字符串本身可以保留在该类的.cpp实现文件中,并且其他任何人都不必了解它们。 (除非它们实际上是不是您的代码定义的,但这不是您描述问题的方式。)