【问题标题】:C++ error only when compiled with no optimizations (GCC)仅在没有优化(GCC)的情况下编译时出现 C++ 错误
【发布时间】:2018-04-06 17:05:46
【问题描述】:

这是一些代码:

#include<iostream>

using namespace std;

class ShowHello {
 public:
    string operator()(int x) {return "hello";}
};

template<typename F>
class A {
 private:
    static F f;
    static inline string foo(const int& x) {
        return f(x);
    }

 public:
    A() {
        cout << "foo: " << foo(10) << endl;
    }
};


int main(int argc, char *argv[])
{
    A<ShowHello> a;
    return 0;
}

这里是我用一些优化编译它:

$ g++ -std=c++11 -O1 -Wall test.cc -o test && ./test
foo: hello

没有优化

$ g++ -std=c++11 -O0 -Wall test.cc -o test && ./test
/tmp/ccXdtXVe.o: In function `A<ShowHello>::foo(int const&)':
test.cc:(.text._ZN1AI9ShowHelloE3fooERKi[_ZN1AI9ShowHelloE3fooERKi]+0x2a): undefined reference to `A<ShowHello>::f'
collect2: error: ld returned 1 exit status

我做错了什么?

还有

$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

【问题讨论】:

  • 声明静态成员变量f,但你从来没有定义它。在优化的构建中,它可能已经优化了,因为它没有被使用。
  • using namespace std; is a bad practice,永远不要使用它。

标签: c++ c++11 templates gcc


【解决方案1】:

您在此处声明一个静态成员变量f

static F f;

然后你在这里odr-use它:

static inline string foo(const int& x) {
    return f(x);
}

这需要f 的定义可用,但您没有提供定义 - 只是声明。这使得程序格式错误,不需要诊断。然而,在实践中,只有在链接器确实需要时才需要定义——在这种情况下,优化的构建只是将调用完全内联,甚至不需要考虑静态成员或您的类。事实上,这些说明包括一些有趣的东西,例如:

    movl    $1819043176, 16(%rsp)  // this is "hell"
    movl    $5, %edx
    movl    std::cout, %edi
    movq    $5, 8(%rsp)
    movb    $111, 4(%rsi)          // this is 'o'

很酷的东西。

无论如何,未优化的构建实际上确实依赖于 f 的定义,因为实际上进行了调用 - 而您没有定义,因此链接器错误。优化后的构建不依赖于f,但为了正确起见,您还是应该定义它。

template <typename F>
struct A { ... };

template <typename F>
F A<F>::f;

【讨论】:

  • 在 C++17 中,您将能够跳过单独的定义步骤,而是在使用 inline static F f; 的类中声明和定义它。如果静态成员变量是constexpr,它也自动是inline,这很好。
猜你喜欢
  • 1970-01-01
  • 2020-11-11
  • 2013-10-07
  • 2011-01-21
  • 2017-08-28
  • 2011-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多