在容器中使用std::unique_ptr
有透明的方法吗?
#include <iostream>
#include <memory>
#include <map>
struct method {
virtual ~method() { std::cout << "f\n"; };
};
typedef std::unique_ptr<method> MPTR;
std::map<int, MPTR> tbl;
void insert(int id, method *m) {
tbl.insert({id,std::unique_ptr<method>(m)});
};
void set(int id, method *m) {
tbl[id] = std::unique_ptr<method>(m);
};
int main(int argc, char **argv) {
insert(1,new method());
set(1,new method());
return 0;
}
我想使用tbl.insert({id,m});
和tbl[id] = m;
等,而不必为每次访问都进行包装/解包。
std::map
。答案 0 :(得分:10)
通常,我们不想隐式创建std::unique_ptr
,因为that can be dangerous。
在此示例中,我建议从unique_ptr
开始,而不是简单的new
。这个makes sure the entire lifetime is tracked。
#include <memory>
int main(int argc, char **argv) {
auto m = std::make_unique<method>();
insert(1, std::move(m));
}
在insert
内,您还可以使用std::move
将所有权转让给该收藏集。
答案 1 :(得分:3)
当您将原始指针传递给函数时,通常不知道在函数退出时,谁将保留指向对象的所有权,即调用方或被调用方。语言中没有任何东西可以指定或强制执行。
因此,通常好的做法是仅在被调用者读取或修改对象但希望调用者保持所有权时才传递原始指针。
在您的示例中,情况并非如此。您希望函数对已分配的method
对象拥有所有权。因此,您应该更改函数以按值传递std::unique_ptr<method>
对象,而不是传递原始method*
指针。这非常明确地表明所有权应从调用者转移到被调用者,例如:
#include <iostream>
#include <memory>
#include <map>
struct method {
virtual ~method() { std::cout << "f\n"; };
};
typedef std::unique_ptr<method> MPTR;
std::map<int, MPTR> tbl;
void insert(int id, MPTR m) {
tbl.insert(std::make_pair(id, std::move(m)));
};
void set(int id, MPTR m) {
tbl[id] = std::move(m);
};
int main()
{
insert(1, MPTR(new method)); // or insert(1, std:::make_unique<method>()) in C++14 and later
set(1, MPTR(new method)); // or set(1, std:::make_unique<method>()) in C++14 and later
return 0;
}
答案 2 :(得分:1)
我想使用
tbl.insert({id,m});
和tbl[id] = m;
,而不必为每次访问都进行包装。
为什么?这对读者隐藏了信息。重要的是要知道是否动态分配了某些内容。
是否存在用于unique_ptr的std容器?特别是
std::map
。
不在标准库中。
如何实现透明接口?
在包装器中存储一个普通容器,提供在需要时创建unique_ptr
的转发功能。迭代器可以自动解包。例如
template <typename T>
class unique_ptr_vector
{
std::vector<std::unique_ptr<T>> _data;
public:
template <typename... Ts>
void emplace_back(Ts&&... xs)
{
_data.emplace_back(std::make_unique<T>(std::forward<Ts>(xs)...));
}
};