当前位置: 首页 > 知识库问答 >
问题:

静态constexpr类成员何时需要类外定义?

长孙高远
2023-03-14

我有以下C 11代码(简化版):

struct Info
{
    const char * name;
    int version;
};

class Base
{
public:
    const Info info;
    Base (Info info) : info (info) {}
};

class Derived : public Base
{
public:
    static constexpr Info info = {"Foobar", 2};
    Derived () : Base (info) {}
};

int main ()
{
    static Derived derived;
    return 0;
}

GCC 4.9.1可以很好地编译和链接此代码。另一方面,Clang 3.5.0抱怨未定义的引用:

/tmp/test-109c5c.o: In function `main':
test.cc:(.text+0x1c): undefined reference to `Derived::info'
test.cc:(.text+0x22): undefined reference to `Derived::info'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

哪个是对的?这个代码合法吗?我对静态Constexr成员规则的理解(主要基于这个问题)是,只有在获取变量的地址时才需要类外定义。但是我没有将Deriv的地址ed::信息或在任何地方使用对它的引用;我只是按值将它传递给Base构造函数。

我发现了各种变通方法:

  • 使两个构造函数(基构造函数和派生构造函数)都为constexpr。这可能是也可能不是实数类的选项,实数类比示例中的类更复杂。无论如何,我要试试

共有1个答案

姚建树
2023-03-14

啊哈,问题似乎是隐式信息(const Info

显然,GCC在优化复制构造函数方面比Clang更积极。如果我使用-fno-elide-构造函数,那么GCC还会抱怨对Derived::信息的未定义引用。

在任何情况下,将Base和Derive构造函数声明为constexr似乎完成了我想要在这里发生的事情,即在编译时初始化Base::信息,而不是在运行时从单独的Derived::信息中复制。

 类似资料:
  • 我有以下示例类<code>Foo</code>和嵌套类<code<Bar</code<,所有内容都是<code>constexpr</code>: 我想测试调用<code>Foo::DoTheThing</code>返回1: 海湾合作委员会和Clang都在这里抱怨,但MSVC没有 GCC表示: 错误: ,或者如果我将< code>Bar的定义移到< code>Foo之外,我可以让GCC和Clang

  • 考虑以下代码: GCC v6.1编译它,叮当声3.8拒绝它,错误如下: 2:错误:没有成员名为'foo'在'U' struct S{静态constexpr int bar=T::foo;}; 哪个编译器是对的? 会不会是因为在我们尝试在中使用它时不是一个完整的类型? 在这种情况下,它应该被认为是GCC的错误,但我想知道我是否正确之前在错误跟踪器上搜索/打开问题… 编辑 与此同时,我已经向GCC打开

  • C++ 类 & 对象 我们可以使用 static 关键字来把类成员定义为静态的。当我们声明类的成员为静态时,这意味着无论创建多少个类的对象,静态成员都只有一个副本。 静态成员在类的所有对象中是共享的。如果不存在其他的初始化语句,在创建第一个对象时,所有的静态数据都会被初始化为零。我们不能把静态成员的初始化放置在类的定义中,但是可以在类的外部通过使用范围解析运算符 :: 来重新声明静态变量从而对它进

  • 本文向大家介绍Java类的静态成员是什么?,包括了Java类的静态成员是什么?的使用技巧和注意事项,需要的朋友参考一下 在Java中,静态成员是属于该类的成员,您可以在不实例化该类的情况下访问这些成员。 static关键字可以与方法,字段,类(内部/嵌套),块一起使用。 静态方法-您可以使用关键字static创建静态方法。静态方法只能访问静态字段,方法。要访问静态方法,无需实例化该类,只需将类名用

  • 本文向大家介绍什么是C#类的静态成员?,包括了什么是C#类的静态成员?的使用技巧和注意事项,需要的朋友参考一下 我们可以使用static关键字将类成员定义为static。当我们将一个类的成员声明为静态成员时,这意味着无论创建了多少个该类的对象,静态成员只有一个副本。 关键字static表示该类仅存在成员的一个实例。静态变量用于定义常量,因为可以通过调用该类而不创建其实例来检索其值。静态变量可以在成

  • 我正在装一个应用程序,它工作得很好。但当我使用 在OuterClass中,并通过