【问题标题】:What are the (dis)advantages of a constant declared in an anonymous namespace vs a function-scope static constant?在匿名命名空间中声明的常量与函数范围的静态常量有什么(缺点)优点?
【发布时间】:2016-03-30 14:34:58
【问题描述】:

我想定义一个函数,当给定一个整数时,它会返回一个字符串。像这样:

# Pseudocode
function get_string(i)
  return my_string_array[i]
end

字符串将被硬编码到应用程序中。函数原型在头文件中声明:

// header.h
const std::string &get_string(const int i);

在我看来,我有两个选项来声明硬编码字符串。

选项#1:在get_string中声明一个静态变量

// source.cpp
const std::string &get_string(const int i)
{
    static const std::string values[] = {
        std::string("foo"),
        std::string("bar"),
        std::string("baz"),
    };

    // Assume bounds checking is performed on i.

    return values[i];
}

选项 #2:在匿名命名空间中声明全局常量

// source.cpp
namespace
{
    const std::string values[] = {
        std::string("foo"),
        std::string("bar"),
        std::string("baz"),
    };
}

const std::string &get_string(const int i)
{
    // Assume bounds checking is performed on i.
    return values[i];
}

对于这个有限的用例,这些声明在功能上是否等效?程序对待函数中的静态常量是否不同于全局声明的常量或匿名命名空间中声明的常量?

我知道明显的可访问性差异(即,在本地命名空间中声明的常量可全局用于同一翻译单元中定义的所有函数),但这可以根据场景的不同方式被认为是一种优势,所以对于这个问题,这个区别可以省略。

【问题讨论】:

  • 我能想到的唯一区别是全局变量在程序开始时在输入main之前被初始化;而函数静态仅在函数第一次调用时才被初始化。在您的情况下,区别可能并不重要。
  • 在函数本身内部定义它,如果没有其他人直接使用它(理想情况下没有人应该这样做,否则函数本身就没有用途)。除此之外,在访问元素之前,您必须检查 i 的超出范围的值。
  • @Nawaz - 不要害怕,肯定会执行边界检查:-)
  • 根据您的用例,如果在编译时知道i,您可以将get_string 设为模板函数,将i 作为模板参数并使用模板特化返回适当的字符串.您可能在运行时确定i,所以这可能行不通,只是抛出选项。

标签: c++ static namespaces constants


【解决方案1】:

在 get_string 函数中定义为静态数组的字符串将在第一次 get_string 调用时构建,而全局命名空间中的字符串将在应用程序启动时构建。

因此,这两种方法可能出现的问题是不同的。例如,如果您在全局范围内定义字符串,那么您不应该在执行 main 之前使用它,否则您永远不知道它们是否被构造。如果你在 get_string 中使用静态构造,至少在 c++11 之前你可能会遇到线程问题,之后魔法静态应该会为你解决这个问题。

为什么不把它们放在const char* 全局数组中?

[编辑]

正如我上面建议的那样,全局数组不是正确的方法。您需要考虑的另一件事是使用选项 1,但不是创建字符串数组,而是创建 const char* 字符串文字数组。 std::string 对象的数组将复制您的字符串文字。您可能还必须返回 const char* - 所以这可能不是您想要的。

【讨论】:

  • 你为什么不把它们放在 const char* 全局数组中? ..为什么是const char*?为什么是global
  • 我认为这可以解决“静态初始化顺序惨败”问题,我的意思是“const char*”的静态数组。
  • 我同意推荐使用Option #1
  • "static initialization order fiasco"std::string 的元素无关,因此如果它在这种情况下会出现,则无法修复通过将std::string 替换为const char*
  • 呃,对了——这样的全局数组仍然需要在初始化期间分配。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-15
  • 1970-01-01
  • 2010-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多