我想在我的类中有一个static const
char
数组。GCC抱怨说我应该使用constexpr
,尽管现在它告诉我这是一个未定义的引用。如果我将数组设为非成员,那么它就会编译。怎么一回事?
// .hpp
struct foo {
void bar();
static constexpr char baz[] = "quz";
};
// .cpp
void foo::bar() {
std::string str(baz); // undefined reference to baz
}
发布于 2017-10-13 06:02:36
这确实是C++11中的一个缺陷--正如其他人所解释的那样,在C++11中,静态常量表达式成员变量不同于任何其他类型的常量表达式全局变量,它具有外部链接,因此必须在某个地方显式定义。
还值得注意的是,在使用优化进行编译时,您经常可以在没有定义的情况下使用静态常量表达式成员变量,因为它们最终可以在所有使用中内联,但是如果您在没有进行优化的情况下进行编译,那么您的程序将无法链接。这使得这成为了一个非常常见的隐藏陷阱--你的程序在优化的情况下编译得很好,但是一旦你关闭了优化(可能是为了调试),它就无法链接。
不过,好消息是-这个缺陷已经在C++17中修复了!不过,这种方法有点复杂:在C++17中,静态常量表达式成员变量are implicitly inline。拥有inline applied to variables是C++17中的一个新概念,但它实际上意味着它们在任何地方都不需要显式定义。
发布于 2016-04-19 22:40:22
更优雅的解决方案是不是将char[]
改为:
static constexpr char * baz = "quz";
这样,我们可以在一行代码中定义/声明/初始化式。
发布于 2018-08-30 19:49:46
对于静态成员的外部链接,我的变通方法是使用constexpr
引用成员getter(这不会遇到问题@gnzlbg作为对@deddebme的回答的注释提出的)。
这个习惯用法对我来说很重要,因为我不喜欢在我的项目中有多个.cpp文件,并试图将数量限制为一个,其中只包含#include
和一个main()
函数。
// foo.hpp
struct foo {
static constexpr auto& baz() { return "quz"; }
};
// some.cpp
auto sz = sizeof(foo::baz()); // sz == 4
auto& foo_baz = foo::baz(); // note auto& not auto
auto sz2 = sizeof(foo_baz); // 4
auto name = typeid(foo_baz).name(); // something like 'char const[4]'
https://stackoverflow.com/questions/8016780
复制相似问题