std::auto_ptr 的最佳实践
我刚刚习惯使用 std::auto_ptr 的智能指针。
假设我想调用一个同时具有 auto_ptr 和普通指针的函数。
auto_ptr<uint32> data_smart(new uint32[123])]);
uint32 data_fix[123];
uint32* data_dumb = new uint32[123];
processData(data_smart);
processData(data_fix);
processData(data_dumb);
在不超载的情况下,最佳实践是什么?有带有 uint32* 参数的 processData 函数吗?在这种情况下,我可以使用 .get() 将智能指针强制转换为 uint32* 吗?或者说我应该采取什么方法呢? 提前致谢!
I'm just getting used to smart pointers using std::auto_ptr.
Assume that I want to call a function with both auto_ptr and normal Pointers.
auto_ptr<uint32> data_smart(new uint32[123])]);
uint32 data_fix[123];
uint32* data_dumb = new uint32[123];
processData(data_smart);
processData(data_fix);
processData(data_dumb);
What is the best practice for this without overloading? Having the processData function with a uint32* argument? Can I cast the smart pointer to uint32* for this case with .get()? Or what is the way I should do it?
Thanks in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
1.
不要那样做。
auto_ptr
仅适用于标量(它调用delete
而不是delete[]
)。2.
auto_ptr
拥有它指向的对象,因此除非您想将所有权传递给该函数(在您的代码中不需要),否则该函数应该接受普通指针。因此,您应该将调用更改为:以便明确表示
data_smart
继续拥有该对象。1.
Don't do that.
auto_ptr
works with scalars only (it callsdelete
rather thandelete[]
).2.
auto_ptr
owns the object it points to, so unless you want to pass the ownership to that function (in your code you don't), the function should accept a normal pointer. So you should change the call to:in order to explicitly express that
data_smart
continues to own the object.编辑:诺亚·罗伯茨对你的问题的评论是这里更大的问题,但这回答了所提出的问题,即使示例代码是错误的......
如果您想在不重载的情况下执行此操作,则适用于所有这些的唯一选择是使该方法采用哑指针参数。
不可以。使用
std::auto_ptr::get()
。EDIT: Noah Roberts' comment on your question is the bigger issue here, but this answers the question asked even if the example code is wrong....
If you want to do it without overloading, the only option that's going to work for all of these is to make the method take a dumb pointer parameter.
No. Use
std::auto_ptr<t>::get()
.首先,您不使用指向数组的指针来初始化 auto_ptr。它不受支持,最终会导致内存泄漏。 std::auto_ptr 仅处理单个对象。
如果您仍然想使用 std::auto_ptr,但仅适用于单个对象,则需要记住 std::auto_ptr 在复制构造函数中转移所有权。这意味着如果您按值传递 data_smart,则在调用 processData 后,本地 auto_ptr (data_smart) 将不会保留任何内存。
最后,您可能想使用 boost::scoped_array 或 boost::shared_array。
First of all, you don't initialize auto_ptr with a pointer to array. It's not supported, and you'll end up with memory leaks. std::auto_ptr handles only single objects.
If you still want to use std::auto_ptr, but for single objects only, you need to remember that std::auto_ptr transfers ownership in copy constructor. That means that your local auto_ptr (data_smart) won't hold any memory after you call processData if you pass data_smart by value.
In the end, you probably want to use boost::scoped_array or boost::shared_array.
最佳实践是不要使用
auto_ptr
。它将在 C++0x 中弃用,并由std::unique_ptr
取代(参考:C++0x 标准草案,附录 D,第 10 段)。与此同时,替代方案包括 std::tr1::shared_ptr 和 boost::scoped_ptr。但您的示例是一个数组,而这些指针类型不适用于数组。您可以使用
boost::shared_array
来实现这一点。然而标准本身没有数组智能指针。这可能是因为他们认为您应该使用
std::vector
(或者当您在编译时知道大小时使用std::array
来表示固定大小的数组)。鉴于此,您可以执行以下操作:现在,您可以调用接受常规普通
uint32*
的函数,因为vector
和std:: tr1::array
s 有方法让您以 C 风格数组的指针的形式访问数据:如果您打算这样做,我会强烈建议添加边界检查。将第二个参数传递给
processData
以及数组的大小:如果您可以完全放弃 C 风格的指针/数组,更好的方法可能是通过引用传递:
但这仅适用于
向量
,而不是std::tr1::array
或任何其他容器。因此,更进一步,您可以使用接受迭代器的模板:最后一个模板可以工作,因为指向 C 样式数组的指针可以用作迭代器。
Best practice is to not use
auto_ptr
. It will be deprecated in C++0x and replaced bystd::unique_ptr
(Reference: C++0x Draft Standard, Appendix D, Paragraph 10). In the meantime, alternatives includestd::tr1::shared_ptr
andboost::scoped_ptr
.But your example is an array, and those pointer types are not for arrays. You can use
boost::shared_array
for that.However the Standard itself does not have array smart pointers. That’s probably because they believe you should be using
std::vector
instead (orstd::array
for fixed size arrays when you know the size at compile time). Given that, you could do the following:Now, you can call your function that accepts a regular plain-old
uint32*
because bothvector
s andstd::tr1::array
s have methods to give you access to the data as a pointer to a C-style array:I would strongly recommend adding bounds-checking if you are going to do this. Pass a second argument to
processData
with the size of the array:And if you can abandon C-style pointer/arrays entirely, a better way might be to pass by reference:
But this only works for
vector
s, notstd::tr1::array
s or any other container. So, taking it one step further, you could use a template that accepts iterators:The last one works because pointers to C-style arrays can be used as iterators.
在您的情况下,使用向量是最安全的选择:
processData 的签名理想情况下应该是:
但是,这个签名更常用:
在这两种情况下,您都可以使用向量:
In your situation using a vector is the safest choice:
The signature of processData should ideally be:
However, this one is more frequently used:
In both cases you can use the vector:
尽管为什么您应该使用 auto 和哑(正如您所说的)指针将相同的数据指向相同的名称函数而不重载,但 auto_ptr 不能在数组上使用,因为它调用了错误类型的删除。
看看这个:http://learningcppisfun。 blogspot.com/2007/05/custom-deleters-with-smart-pointers.html
另外看看这个关于数组智能指针的问题:数组的 auto_ptr
Not withstanding why you should want to use auto and dumb (as you put it) pointers for the same data to the same name function without overloading, auto_ptr cannot be used on arrays because it calls the wrong sort of delete.
Have a look at this: http://learningcppisfun.blogspot.com/2007/05/custom-deleters-with-smart-pointers.html
Also have a look at this SO question regarding smart pointers to arrays: auto_ptr for arrays
让我觉得有趣的是,data_smart 变量是这三个变量中最愚蠢的一个。也就是说,当该作用域结束时,auto_ptr 析构函数将对其指针调用
delete
而不是delete[]
,这会导致 UB (这比可能的内存更糟糕)从 data_dumb 泄漏)。所以,重点是不要对数组使用 auto_ptr,而使用向量。
进入真正的问题。首先,如果可能的话,使用引用参数而不是指针参数。如果这不可能,请使用裸指针,并且
auto_ptr::get()
可以访问底层指针。It amuses me that the data_smart variable is the dumbest of the three. That is, when that scope ends, the auto_ptr destructor is going to call
delete
on its pointer and notdelete[]
which leads to UB (which is worse than the possible memory leak from data_dumb).So, the point is don't use auto_ptr for arrays, use vector.
Onto the real question. First, if possible use reference arguments instead of pointer arguments. If this isn't possible use bare pointers and
auto_ptr::get()
gives access to the underlying pointer.忽略已经被锤击的不要在数组上使用 auto_ptr 。
看来你的方法不会取得所有权,所以剩下的问题是它会改变吗?
processData( uint32* )
这是一种选择,但可能不是最好的。processData( uint32[123] )
如果您不进行编辑(123 开始推送一些复制)。processData( uint32 &[123] )
by ref 并根据需要应用 const。您可以使用 get() 获取智能指针的指针内容,它已经“类型化”了,因此无需对其进行强制转换。
旁白:
如此原始级别的数据和操作应该在一个类中,您甚至可能不需要将成员变量传递到成员函数中。
Ignoring the already HAMMERED don't use auto_ptr on array.
It appears your method will not take ownership, so the remaining question is will it be changed?
processData( uint32* )
Thats one option, but maybe not the best.processData( uint32[123] )
if your not editing (123 is starting to push some copying).processData( uint32 &[123] )
by ref and apply const as necessary.You can get the pointer content of the smart pointer using get(), it's already 'typed' so no need to cast it.
Aside:
Data and manipulation of at such a raw level should be in the one class, you probably don't even need to pass what should be a member variable into a member function.