3

我目前正在学习 C++,但遇到了一些麻烦。

我已经通过使用大量开发了一个程序#define,但我想static const改用(碰撞/类型/范围......)。

所以,我现在有类似的东西:

file1.hpp

 class A {
   public:
     static const std::string MY_CONST_VAR;
 };

file1.cpp

 const std::string A::MY_CONST_VAR = "some string";

file2.cpp

 static std::string arrayOfString[] = {
   A::MY_CONST_VAR,
   ...
  };

我的代码编译时没有警告/错误(使用 -W -Wall -Wextra -Werror 标志编译)。

但是,当我尝试运行它时,会导致段错误。

我用 valgrind 运行它,它给了我以下输出:

==11239== Invalid read of size 4
==11239==    at 0x5F525CB: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==11239==    by 0x40D076: _GLOBAL__sub_I__ZN16GraphicInterface13DEFAULT_WIDTHE (GraphicInterface.cpp:42)
==11239==    by 0x51AC7C: __libc_csu_init (in /home/simon/PSU_2013_zappy/gui/gui_zappy)
==11239==    by 0x66D8E54: (below main) (libc-start.c:246)
==11239==  Address 0xfffffffffffffff8 is not stack'd, malloc'd or (recently) free'd

因此,段错误发生在 arrayOfString 实例化期间。我认为问题在于 arrayOfInt 是在常量之前分配的。但在那种情况下,是否可以为此目的使用 static const ?

我不知道如何修补这个问题。我做错了吗?有更好的方法吗?如何解决这个问题?

4

2 回答 2

4

感谢评论,我终于通过使用constexpr关键字解决了这个问题。

它给了我以下工作代码:

file1.hpp

class A {
  public:
    static constexpr char MY_CONST_VAR[] = "some string";
};

file1.cpp

const char A::MY_CONST_VAR[];

file2.cpp

static std::string arrayOfString[] = {
  A::MY_CONST_VAR,
  ...
};
于 2014-06-19T00:51:13.783 回答
3

static-init-fiasco 问题的通用解决方法是将 static 包装在函数中,因为函数内部的变量在调用函数之前不会对其初始化程序进行评估。

当它是一个长度由初始化器数量决定的数组时,这并不是那么简单。但是,恕我直言,访问全局 C 样式数组是一种糟糕的设计:要么每次使用数组时都必须通过范围检查来污染代码,要么冒着越界访问的风险;和数组绑定错误是运行时最难调试的一些错误。

我个人会将代码替换为:

std::string &lookup_string(size_t n)
{
    static std::string arrayOfString[] = { A::MY_CONST_VAR(), .... };

    if ( n >= dimof(arrayOfString) ) throw....
    return arrayOfString[n];
}

并且在另一个文件中,如果constexpr不可用:

std::string MY_CONST_VAR() { return "some string"; }

现在没有静态的惨败。

注意。我假设你想要写访问权限arrayOfString,因为你没有声明它const。如果它们应该是只读的,那么可以进行进一步的改进。

于 2014-06-19T01:31:25.317 回答