对于没有提供简单的可运行故障代码表示歉意。这个错误是需要大量重构的较大代码库的一部分。
我的代码遇到了一个非常奇怪的链接问题,到目前为止我还无法解决。对于一些字符串,我有一个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;