创建带有const char*的对象时使用std::make_unique时发生链接错误



对于没有提供简单的可运行故障代码表示歉意。这个错误是需要大量重构的较大代码库的一部分。

我的代码遇到了一个非常奇怪的链接问题,到目前为止我还无法解决。对于一些字符串,我有一个static constexpr const char *和局部std::sunique_ptr的类。指针指向一个不同的模板类,该模板类包含另一个模板类(#2)。

主要类如下(节略):

class Manager {
public:
Manager();
virtual ~Manager();
private:
// Topic Constants
static constexpr const char* kActuatorsCommand = "ActuatorsCommand";
static constexpr const char* kActuatorsProxy = "ActuatorsProxy";
std::unique_ptr<DataReader> faults_;
};

因此,DataReader构造器采用两个const string &参数。

如果我将faults_声明为一个常规的旧指针,并使用new创建它,那么代码就会运行并链接得很好:DataReader *faults_ = new DataReader<uint32_t>(kActuatorsCommand, kActuatorsProxy)

但是,如果我使用std::make_unique,链接器会抱怨对那些static const char*字符串有未定义的引用,即使它们在类的头中也是如此。

此外,如果我删除#2类,所有链接都很好。

使用gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0


我知道这可能是一个相当模糊的问题,但希望能找到一些方向。

此外,这个问题可能与这个问题类似。然而,在我的例子中,所有的东西都在一个二进制上。


更新:终于找到了如何复制它。

class DataReader {
public:
explicit DataReader(const std::string& topic, const std::string& library_name)
: topic_(topic),
library_name_(library_name) {
}
private:
const std::string name_;
const std::string topic_;
const std::string library_name_;
};

#include <memory>
#include "DataReader.h"
class Manager {
public:
Manager();
virtual ~Manager();
private:
// Topic Constants
static constexpr const char* kActuatorsCommand = "ActuatorsCommand";
static constexpr const char* kActuatorsProxy = "ActuatorsProxy";
std::unique_ptr<DataReader> faults_;
};

Manager::Manager() {
faults_ = std::make_unique<DataReader>(kActuatorsCommand, kActuatorsProxy);
}
Manager::~Manager() {}

使用-o0编译时,代码链接失败。与-03连接良好。

g++ -O0 -Wall -Wconversion -lstdc++ -pthread -std=c++14 -o ex3 src/ex3.cpp
/tmp/ccJebZ18.o: In function `Manager::Manager()':
ex3.cpp:(.text+0x41): undefined reference to `Manager::kActuatorsProxy'
ex3.cpp:(.text+0x48): undefined reference to `Manager::kActuatorsCommand'
collect2: error: ld returned 1 exit status
Makefile:8: recipe for target 'ex3' failed

我认为这与内联有关

函数或静态成员变量中使用的constexpr说明符(由于C++17)声明意味着内联

使用-O3-O0 -std=c++17编译代码时,静态变量可能是内联的,从而避免未定义的引用。

我做了一些挖掘,发现:

如果(且仅当)静态成员具有类外定义

来自Bjarne Stroustrup的C++常见问题。将以下代码添加到类主体之外的示例中,使其使用-std=c++14:进行编译

constexpr const char* Manager::kActuatorsCommand;
constexpr const char* Manager::kActuatorsProxy;

相关内容

  • 没有找到相关文章

最新更新