是否使用unique_ptr作为所有权和原始指针
Use unique_ptr for ownership and raw pointer otherwise?
我是C++11,正在编写一些代码。我有
class X { /* */ };
class A {
std::vector<X*> va_x;
};
class B {
std::vector<X*> vb_x;
std::vector<A> vb_a;
};
A类中"va_X"的X*s指向B类中"vb_X"也指向的对象。
现在我想使用智能指针。对我来说,很明显,类B拥有由X*指向的对象的所有权(特别是因为我的A实例属于B)
所以我应该在B:中对X使用unique_ptr
class B {
std::vector<unique_ptr<X>> vb_x;
std::vector<A> vb_a;
};
我的问题是,我应该为A班做什么?我应该保留原始指针吗?通过这样做,在我的单元测试中,我必须承认这会导致尴尬的事情(imo),例如(不要担心封装,这不是重点):
unique_ptr<X> x(new X());
A a;
a.va_x.push_back(&(*x)); //awkward, but what else can I do?
A.vb_a.push_back(a); //ok
B.vb_x.push_back(move(x)); //ok
您可以使用x.get()
,它将返回内部指针。
除此之外,是的,使用原始指针来处理非拥有引用是可行的,另请参阅此问题。
正如Xeo在回答中所说,解决方案通常是使用x.get()
。
有一个FILE
的例子,它在需要访问时使用x.get()
:
void file_deleter(FILE *f)
{
fclose(f);
}
[...]
{
std::unique_ptr<FILE, decltype(&file_deleter)>
f(fopen("/tmp/test.tmp", "rw"), &file_deleter);
// read/write use f.get() as in:
fread(buf, 1, sizeof(buf), f.get());
fwrite(buf, 1, sizeof(buf), f.get());
// fclose() gets called in the deleter, no need to do anything
}
但是,在您的情况下,您需要使用x.release()
。
A a;
{
unique_ptr<X> x(new X());
a.va_x.push_back(&(*x)); // this is wrong
}
// here a[0] is a dangling pointer
&(*x)
将获得原始指针并在a
矢量中进行复制。但是,当unique_ptr<>
超出作用域时,该指针将被删除。因此,在}
之后,a
向量中的指针不再是好的(尽管它可能会工作一段时间。)
传输裸指针的正确方法是使用release()
函数,如下所示:
a.va_x.push_back(x.release()); // this works
在这一行之后,指针仅在a
向量中。它是从唯一指针中发布的,其理念是调用方现在负责管理该资源。
重要提示:push_back()
可能抛出(bad_alloc
),如果发生这种情况,则资源将丢失。为了避免这个问题(以防您的软件捕获bad_alloc
并继续运行),您需要首先在向量中保留空间,如下所示:
a.va_x.reserve(a.va_x.size() + 1); // malloc() happens here
a.va_x.push_back(x.release()); // no `bad_alloc` possible here
这样,当资源仍然附加到unique_ptr
时,bad_alloc
将发生在该语句上,并且在出现异常时不会泄漏它。
尽管如此,你可能需要一个shared_ptr
。这些可以毫无问题地复制。unique_ptr
更适用于一次被分配然后被遗忘的资源,一个函数返回或一个对象被删除。当涉及(许多)副本时,shared_ptr
更有意义。
class X
{
typedef std::shared_ptr<X> pointer_t;
[...]
}
class A
{
std::vector<X::pointer_t> va_x;
}
X::pointer_t x(new X());
A a;
a.va_x.push_back(x); // much cleaner and the pointer is still managed
- 将浮动的heightmap数组导出为16位原始值
- 给定一个向量,如何找到该向量的所有子集和的原始索引
- 我是否需要在下一次转移时将所有权*转移回转移队列
- 有没有办法从非C/C++文件中读取C++原始字符串文字的内容
- 是否可以将llvm::FunctionType转换为C/C++原始函数指针
- 智能指针概念所有权和寿命
- 如何将原始字节附加到 std::vector?
- 从堆栈分配的原始指针构造智能指针
- 如何重写全局方法名称以在调用原始方法之前将我的代码推到前面
- 将unique_ptr分配给原始指针
- 是否可以从 OpenGL 缓冲区获取原始大小的像素?
- 使用 OpenSSL 从内存中读取原始 SSL/TLS 证书
- 如何将唯一指针的 std::vector 转换为原始指针的 std::span?
- 从原始字节解码协议缓冲区(以 C++为单位)
- C ++如何在原始抽象类中创建一个函数,该函数接受派生类的输入
- C++:尝试使用等效的 STL 算法消除原始循环
- 将原始指针的所有权转移到unique_ptr
- 是否使用unique_ptr作为所有权和原始指针
- 为原始指针(如所有权语义)返回unique_ptr的不良做法
- 声明现有原始指针所有权的正确方法