这是我遇到的一个问题的最小例子,我无法弄清楚应该如何解决它:
#include <vector>
#include <memory>
class Thing {
};
class App {
public:
std::vector<std::unique_ptr<Thing>> thingVec;
void add_thing(Thing*);
};
void App::add_thing(Thing* thing) {
thingVec.push_back(std::unique_ptr<Thing>(thing));
}
int main() {
App app;
Thing thing;
app.add_thing(&thing);
}
这会编译并运行,但是,在到达main,segfaults并吐出的时候没有问题:
Error in `/path/testapp': free(): invalid pointer: 0x00007fff97118070 ***
任何可能的帮助?我想存储(唯一)指针的原因是Thing通常会被派生出来。
编辑: 一个有效的解决方案:
#include <vector>
#include <memory>
class Thing {
};
class App {
public:
std::vector<std::unique_ptr<Thing>> thingVec;
void add_thing(Thing*);
};
void App::add_thing(Thing* thing) {
thingVec.push_back(std::unique_ptr<Thing>(thing));
}
int main() {
App app;
Thing* thing = new Thing;
app.add_thing(thing);
}
但据我所知,我应该能够完全避免使用new,并使用make_unique?我似乎无法找到实际定义的make_unique的位置。
编辑2:
这更合适吗?有没有一个不那么混乱的方式来做到这一点?否则,它运作良好。
#include <vector>
#include <memory>
#include <iostream>
class Thing {
public:
int foo = 42;
};
class App {
public:
std::vector<std::unique_ptr<Thing>> thingVec;
void add_thing(std::unique_ptr<Thing>);
};
void App::add_thing(std::unique_ptr<Thing> thing) {
thingVec.push_back(std::move(thing));
}
int main() {
App app;
app.add_thing(std::unique_ptr<Thing>(new Thing()));
std::cout << app.thingVec.back()->foo << std::endl;
}
因为我可能最终得到像
这样的行app.thingVex.back()->barVec.back()->blahMap.emplace("flop", std::unique_ptr<Tree>(new Tree));
答案 0 :(得分:6)
std::unique_ptr
正在尝试删除堆栈分配的Thing
实例。
您的错误基本上在以下几行:
Thing thing;
app.add_thing(&thing);
答案 1 :(得分:1)
您应该将本地对象传递给unique_ptr。
替换
Thing thing;
app.add_thing(&thing);
与
app.add_thing(new Thing);
如果您还想编辑对象
Thing *thing = new Thing;
// thing->some_val = val;
app.add_thing(thing);
确保不要在应用程序中两次添加相同的对象,因为std :: unique_ptr获取指针指针的所有权将被尝试释放超过1次。
答案 2 :(得分:1)
add_thing
的界面错误,因为它需要&#34;非拥有&#34;指向Thing
的原始指针然后假设它可以通过从中构造unique_ptr
来获取传入的对象的完全所有权。
如果您将add_thing
更改为按值unique_ptr<Thing>
,则会阻止调用者隐式转换原始指针,并且不会需要构造新的unique_ptr
堆分配到add_thing
函数中。
e.g。
void App::add_thing(std::unique_ptr<Thing> thing) {
thingVec.push_back(std::move(thing));
}
int main() {
App app;
app.add_thing(std::make_unique<Thing>());
}
(请注意,std::make_unique
是未来的功能; std::unique_ptr<Thing>(new Thing)
现在可以使用。)
答案 3 :(得分:0)
您未正确转让所有权。您可以使用带有自定义删除器的共享指针来防止删除引用的变量:
#include <vector>
#include <memory>
class Thing {
};
class App {
public:
std::vector<std::shared_ptr<Thing>> thingVec;
void add_thing(std::shared_ptr<Thing>&& thing) {
thingVec.push_back(std::move(thing));
}
};
template<typename T>
inline std::shared_ptr<T> make_no_delete(T& value)
{
return std::shared_ptr<T>(&value, [](void*){});
}
int main() {
App app;
Thing thing;
// Add without transferring ownership:
app.add_thing(make_no_delete(thing));
// Add and transfer ownership:
app.add_thing(std::make_shared<Thing>());
}