使用 C++11 编译时出现未定义的引用错误

发布于 2025-01-13 16:00:44 字数 1037 浏览 2 评论 0原文

示例程序在这里:

test.h

#pragma once
#include <bitset>

class Foo{
public:
    constexpr static std::bitset<9> hori1{0b111000000};
    bool Bar(const std::bitset<9> cells);
};

test.cpp

#include <bitset>
#include "test.h"

bool Foo::Bar(const std::bitset<9> cells){
    return hori1.any();
}

int main(){
    return 0;
}

在没有 --std=c++11 的情况下编译此程序时,一切正常。

$ g++ -c test.cpp
$ g++ test.o

但是当包含该标志时,我得到这样的信息:

$ g++ -c --std=c++11 test.cpp
$ g++ test.o
/usr/bin/ld: test.o: warning: relocation against `_ZN3Foo5hori1E' in read-only section `.text'
/usr/bin/ld: test.o: in function `Foo::Bar(std::bitset<9ul>)':
test.cpp:(.text+0x17): undefined reference to `Foo::hori1'
/usr/bin/ld: warning: creating DT_TEXTREL in a PIE
collect2: error: ld returned 1 exit status

为什么这种情况只发生在 C++11 中?据我所知,test.h 已正确包含,因此 hori1 应该在 Foo 中可见。任何帮助表示赞赏。

The example program is here:

test.h

#pragma once
#include <bitset>

class Foo{
public:
    constexpr static std::bitset<9> hori1{0b111000000};
    bool Bar(const std::bitset<9> cells);
};

test.cpp

#include <bitset>
#include "test.h"

bool Foo::Bar(const std::bitset<9> cells){
    return hori1.any();
}

int main(){
    return 0;
}

When compiling this program without the --std=c++11 everything works fine.

$ g++ -c test.cpp
$ g++ test.o

But when the flag is included, I get this:

$ g++ -c --std=c++11 test.cpp
$ g++ test.o
/usr/bin/ld: test.o: warning: relocation against `_ZN3Foo5hori1E' in read-only section `.text'
/usr/bin/ld: test.o: in function `Foo::Bar(std::bitset<9ul>)':
test.cpp:(.text+0x17): undefined reference to `Foo::hori1'
/usr/bin/ld: warning: creating DT_TEXTREL in a PIE
collect2: error: ld returned 1 exit status

Why is this happening only in C++11? As far as I know, test.h is correctly included and therefore hori1 should be visible from within Foo. Any help is appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

许一世地老天荒 2025-01-20 16:00:44

hori1静态。您必须在类的实现中定义静态数据成员。

测试.cpp

constexpr std::bitset<9> Foo::hori1;

bool Foo::Bar(const std::bitset<9> cells){
    return hori1.any();
}

int main(){
    return 0;
}

hori1 is static. You have to define static data members in the implementation of the class.

test.cpp:

constexpr std::bitset<9> Foo::hori1;

bool Foo::Bar(const std::bitset<9> cells){
    return hori1.any();
}

int main(){
    return 0;
}
故人爱我别走 2025-01-20 16:00:44

问题是,在 C++11 中,我们必须在类外部的一个翻译单元中为 static constexpr 声明添加相应的定义 > 类的数据成员(如果使用了 odr)。下面更详细地解释了这一点:

C++11

class Foo
{
public:
    static constexpr int OUT_OF_BOUNDS_VALUE = -9999; //THIS IS A DECLARATION IN C++11 and C++14
    //other members here
};

在上面的代码片段(适用于 C++11C++14)中,我们有一个 <类内部静态数据成员OUT_OF_BOUNDS_VALUE的strong>声明。因此,在恰好一个翻译单元中,我们必须提供相应的定义。否则,您将收到链接器错误,可以在此处查看。

也就是说,在 恰好一个 翻译单元中,我们应该编写:

constexpr int Foo::OUT_OF_BOUNDS_VALUE;//note no initializer

在使用 没有初始化程序程序将运行。 演示

C++17

class Foo
{
public:
    static constexpr int OUT_OF_BOUNDS_VALUE = -9999; //THIS IS A DEFINITION IN C++17
    //other members here
};

在上面的代码片段中(适用于C++17< /em>)我们在类内部有静态数据成员OUT_OF_BOUNDS_VALUE定义。因此,从 C++17 开始,我们不必在其他任何地方提供 OUT_OF_BOUNDS_VALUE 的定义,因为我们已经在类中定义了它,因此是同一个程序工作,没有任何链接器错误。

The problem is that in C++11, we have to add a corresponding definition outside the class in exactly one translation unit for a static constexpr declaration of a class' data member(if odr-used). This is explained in more detail below:

C++11

class Foo
{
public:
    static constexpr int OUT_OF_BOUNDS_VALUE = -9999; //THIS IS A DECLARATION IN C++11 and C++14
    //other members here
};

In the above code snippet(which is for C++11,C++14), we have a declaration of the static data member OUT_OF_BOUNDS_VALUE inside the class. And so, in exactly one translation unit we have to provide a corresponding definition. Otherwise you'll get a linker error which can be seen here.

That is, in exactly one translation unit we should write:

constexpr int Foo::OUT_OF_BOUNDS_VALUE;//note no initializer

After adding the above out of class definition with no initializer the program will work. Demo

C++17

class Foo
{
public:
    static constexpr int OUT_OF_BOUNDS_VALUE = -9999; //THIS IS A DEFINITION IN C++17
    //other members here
};

In the above code snippet(which is for C++17) we have a definition of the static data member OUT_OF_BOUNDS_VALUE inside the class. So since C++17, we don't have to provide the definition of OUT_OF_BOUNDS_VALUE anywhere else since we already have a definition for it inside the class and thus the same program works without any linker error.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文