我只是习惯使用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 *吗?或者我应该怎么做? 提前谢谢!
答案 0 :(得分:5)
1
auto_ptr<uint32> data_smart(new uint32[123])]);
不要那样做。 auto_ptr
仅适用于标量(它会调用delete
而不是delete[]
)。
2。
auto_ptr
拥有它指向的对象,因此除非你想将所有权传递给该函数(在你的代码中没有),该函数应该接受一个普通的指针。因此,您应该将呼叫更改为:
processData(data_smart.get());
为了明确表示data_smart
继续拥有该对象。
答案 1 :(得分:1)
......没有超载......
如果你想在没有重载的情况下做到这一点,唯一适用于所有这些的选项就是让方法采用哑指针参数。
对于这种情况,我可以将智能指针强制转换为uint32 *吗?
没有。使用std::auto_ptr<t>::get()
。
答案 2 :(得分:1)
首先,不要使用指向数组的指针初始化auto_ptr。它不受支持,最终会导致内存泄漏。 std :: auto_ptr只处理单个对象。
如果您仍想使用std :: auto_ptr,但仅对于单个对象,则需要记住std :: auto_ptr在复制构造函数中传输所有权。这意味着如果按值传递data_smart,则在调用processData后,本地auto_ptr(data_smart)将不会保留任何内存。
最后,你可能想使用boost :: scoped_array或boost :: shared_array。
答案 3 :(得分:1)
最佳做法是不使用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
用于固定大小的数组,当您在编译时知道大小时)。鉴于此,您可以执行以下操作:
std::vector<uint32> dataVector;
data.reserve(123);
// or, if the size is always 123:
std::tr1::array<uint32, 123> dataArray;
现在,您可以调用接受常规普通版uint32*
的函数,因为vector
和std::tr1::array
都有方法可以将数据作为指针访问一个C风格的数组:
processData(&dataVector[0]);
processData(dataArray.data());
如果您打算这样做,我会强烈建议添加边界检查。将第二个参数传递给processData
,其大小为数组:
processData(&dataVector[0], dataVector.size());
如果您可以完全放弃C风格的指针/数组,更好的方法可能是通过引用传递:
void processData(std::vector<uint32>& data) {
// process the data
}
// call it like this:
processData(dataVector);
但这仅适用于vector
s,而不适用于std::tr1::array
s或任何其他容器。因此,更进一步,您可以使用接受迭代器的模板:
template <class AnIterator>
void processData(AnIterator begin, AnIterator end) {
for (AnIterator it = begin; it != end; ++it) {
// process each item
}
}
// call it like this
processData(dataVector.begin(), dataVector,end());
// or like this
processData(dataArray.begin(), dataArray.end());
// or even like this (assume c_data is a C-style array):
processData(c_data, c_data + number_of_items_in_c_data);
最后一个可行,因为指向C风格数组的指针可以用作迭代器。
答案 4 :(得分:0)
为什么你不应该使用auto和dumb(如你所说)将相同数据的指针用于相同名称的函数而不会重载,auto_ptr不能在数组上使用,因为它调用了错误的删除类型。
看看这个:http://learningcppisfun.blogspot.com/2007/05/custom-deleters-with-smart-pointers.html
另请参阅有关数组智能指针的SO问题:auto_ptr for arrays
答案 5 :(得分:0)
让我觉得data_smart变量是三者中最愚蠢的。也就是说,当该范围结束时,auto_ptr析构函数将在其指针上调用delete
而不是delete[]
,这将导致UB(这比data_dumb可能的内存泄漏更糟)。
所以,重点是不要将auto_ptr用于数组,使用vector。
在真正的问题上。首先,如果可能,使用引用参数而不是指针参数。如果无法做到这一点,请使用裸指针,auto_ptr::get()
可以访问基础指针。
答案 6 :(得分:0)
忽略已经HAMMERED不要在数组上使用auto_ptr。
没有超载的最佳做法是什么?
看来你的方法不会取得所有权,所以剩下的问题是会改变吗?
将processData函数与uint32 *参数一起使用?
processData( uint32* )
这是一个选择,但可能不是最好的选择
processData( uint32[123] )
如果你没有编辑(123开始推动一些复制)
processData( uint32 &[123] )
通过ref并根据需要应用const。
我可以使用.get()将智能指针强制转换为uint32 *吗?
你可以使用get()获取智能指针的指针内容,它已经'打字'所以不需要强制转换它。
除了: 在这样一个原始级别的数据和操作应该在一个类中,你可能甚至不需要将成员变量应该传递给成员函数。
答案 7 :(得分:0)
在您的情况下,使用矢量是最安全的选择:
std::vector<uint32> data(123);
processData的签名理想情况应为:
void processData(const std::vector<uint32> & data);
但是,这个更频繁使用:
void processData(uint32 * bytes, int length);
在这两种情况下,您都可以使用矢量:
// 1
processData(data);
// 2
processData(data.data(), data.size());