Link 使用 const char 创建对象时使用 std::make_unique 时出错 *
Link error when using std::make_unique when creating object with const char *
很抱歉没有提供简单的可运行故障代码。该错误是需要大量重构的较大代码库的一部分。
我 运行 遇到一个非常奇怪的 link 我的代码问题,到目前为止我无法解决。
我有一个 class 和 static constexpr const char *
用于一些字符串和本地 std::sunique_ptr
。指针指向不同的模板 class,其中包含另一个模板 class (#2).
主要class是这样的(节选):
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
创建它,代码运行并且 links 就好了:DataReader *faults_ = new DataReader<uint32_t>(kActuatorsCommand, kActuatorsProxy)
.
但是,如果我使用 std::make_unique
,link 用户会抱怨说存在对那些 static const char*
字符串的未定义引用,即使它们位于 class.
此外,如果我删除 #2 class 一切 link 都很好。
使用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
编译时代码无法 link。使用 -03
它 link 没问题。
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
我觉得跟内联有关系
A constexpr specifier used in a function or static member variable
(since C++17) declaration implies inline
当您使用 -O3
或 -O0 -std=c++17
编译代码时,静态变量可能是内联的,从而避免了未定义的引用。
我做了一些挖掘并发现:
You can take the address of a static member if (and only if) it has an
out-of-class definition
来自 Bjarne Stroustrup's C++ faq。
将以下代码添加到 class 主体之外的示例,使其使用 -std=c++14
:
进行编译
constexpr const char* Manager::kActuatorsCommand;
constexpr const char* Manager::kActuatorsProxy;
很抱歉没有提供简单的可运行故障代码。该错误是需要大量重构的较大代码库的一部分。
我 运行 遇到一个非常奇怪的 link 我的代码问题,到目前为止我无法解决。
我有一个 class 和 static constexpr const char *
用于一些字符串和本地 std::sunique_ptr
。指针指向不同的模板 class,其中包含另一个模板 class (#2).
主要class是这样的(节选):
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
创建它,代码运行并且 links 就好了:DataReader *faults_ = new DataReader<uint32_t>(kActuatorsCommand, kActuatorsProxy)
.
但是,如果我使用 std::make_unique
,link 用户会抱怨说存在对那些 static const char*
字符串的未定义引用,即使它们位于 class.
此外,如果我删除 #2 class 一切 link 都很好。
使用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
编译时代码无法 link。使用 -03
它 link 没问题。
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
我觉得跟内联有关系
A constexpr specifier used in a function or static member variable (since C++17) declaration implies inline
当您使用 -O3
或 -O0 -std=c++17
编译代码时,静态变量可能是内联的,从而避免了未定义的引用。
我做了一些挖掘并发现:
You can take the address of a static member if (and only if) it has an out-of-class definition
来自 Bjarne Stroustrup's C++ faq。
将以下代码添加到 class 主体之外的示例,使其使用 -std=c++14
:
constexpr const char* Manager::kActuatorsCommand;
constexpr const char* Manager::kActuatorsProxy;