有没有办法使用模板专门化来将 new 与 new[] 分开?
我有一个自动指针类,在构造函数中我传递了一个指针。我希望能够在构造函数中将 new 与 new[] 分开,以便我可以在析构函数中正确调用 delete 或 delete[] 。这可以通过模板专门化来完成吗?我不想在构造函数中传递布尔值。
template <typename T>
class MyAutoPtr
{
public:
MyAutoPtr(T* aPtr);
};
// in use:
MyAutoPtr<int> ptr(new int);
MyAutoPtr<int> ptr2(new int[10]);
I have an auto pointer class and in the constructor I am passing in a pointer. I want to be able to separate new from new[] in the constructor so that I can properly call delete or delete[] in the destructor. Can this be done through template specialization? I don't want to have to pass in a boolean in the constructor.
template <typename T>
class MyAutoPtr
{
public:
MyAutoPtr(T* aPtr);
};
// in use:
MyAutoPtr<int> ptr(new int);
MyAutoPtr<int> ptr2(new int[10]);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
不幸的是,没有。两者都返回相同的类型,
T*
。考虑使用调用适当的重载构造函数的构建器函数:现在您可以按如下方式实例化对象:
Unfortunately, no. Both return the same type,
T*
. Consider using builder functions that call an appropriate overloaded constructor:Now you can instantiate objects as follows:
C++0x 中的 std::unique_ptr 将专门针对动态数组,如下所示。然而,实例化适当的实例将是用户的任务。在语言级别,没有办法区分一个指针和另一个指针。
此外,在一个类中加载如此多的任务可能也不是那么好。例如,boost 有
shared_ptr
和shared_array
。std::unique_ptr
in C++0x will have a specialization for dynamic arrays, somewhat like shown below. However, it will be the user's task to instantiate an appropriate instance. At language level there is no way to distinguish one pointer from another.Furthermore, it might not be that good to load one class with so various tasks. For example, boost has
shared_ptr
andshared_array
.另一方面,您可以使用特定的
make
函数。当然,这意味着您背后有适当的逻辑,但它是封装的。您还可以添加重载,采用
T
来复制传递给新创建的指针的对象等...最后,它也可以通过构造函数的重载来完成...重点是不调用外面的
new
。On the other hand, you could use a specific
make
function.Of course, this means that you have the appropriate logic behind, but it's encapsulated. You can also add overload taking a
T
to copy the object passed into the pointer newly created etc...Finally, it can also be done with overloads of the constructor... the point is not to call the
new
outside.我认为真正的解决方案是摆脱你自己的自动指针类并摆脱 C 风格数组的使用。我知道这已经被说过很多很多次了,但是使用 C 风格的数组确实没有什么意义了。几乎所有你能用它们做的事情都可以使用
std::vector
或boost::array
来完成。这两种类型都会创建不同的类型,因此您可以对它们进行重载。I think the real solution is to get rid of your own autopointer class and to get rid of the use of C-style arrays. I know this has been said many, many times before, but there really isn't much point in using C-style arrays any more. Just about everything you can do with them can be done using
std::vector
or withboost::array
. And both of these create distinct types, so you can overload on them.这是不可能的,因为
new int[X]
产生一个指向数组初始元素的指针。它与int*
具有相同的类型。常见的解决方案之一是使用删除器。删除。向您的类添加一个模板参数,以便您可以为指针传递自定义删除器。它将使您的课程更加通用。您可以像下面这样创建默认删除器:
对于数组,您可以传递自定义删除器:
最简单的实现是:
然后您可以按如下方式使用它:
您可以使您的类更复杂,以便它可以推断出删除器的类型。
It is not possible since
new int[X]
yields a pointer to the initial element of the array. It has the same type asint*
.One of the common solutions is to use deleters. Add one more template argument to your class so you could pass custom deleter for your pointer. It'll make your class more universal. You could create default deleter like the following:
And for arrays you could pass custom deleter:
The simplest implementation will be:
Then you could use it as follows:
You could make your class more complex so it could deduce type for deleter.
new[] 被专门定义为具有指针值,尽管数组到指针的隐式转换无论如何都会启动。
但我不认为你运气不好。毕竟,您的示例不是管理指向
int
的指针,而是管理指向int[10]
的指针。所以理想的方法是正如 Red-Nosed Unicorn 提到的,new int[10] 不会创建 C 风格的数组。如果您的编译器也符合 C 标准,则情况会如此,但 C++ 允许 C 样式数组的数量多于 C 中的 C 样式数组。无论如何,如果您这样询问,
new
将为您创建一个 C 样式数组:不幸的是,
deletecontents;
即使使用int (*contents)[ 也无法工作10];
。编译器被允许做正确的事情:标准没有指定数组像new
一样转换为指针,我相信我记得 GCC 替换了delete[] 并发出警告。但这是未定义的行为。
因此,您将需要两个析构函数,一个用于调用
delete
,一个用于调用delete[]
。由于您无法部分专门化一个函数,因此该功能需要一个部分专门化的帮助程序,出于某种原因,我只是让自己接受;v)
不幸的是,这不适用于动态大小的数组,所以我要写下另一个答案。
new[]
is specifically defined to have pointer value despite the array-to-pointer implicit conversion that would kick in anyway.But I don't think you're out of luck. After all, your example isn't managing a pointer to an
int
, it's managing a pointer to anint[10]
. So the ideal way isAs Red-Nosed Unicorn mentions,
new int[10]
does not create a C-style array. It will if your compiler complies to the C standard as well, but C++ allows C-style arrays to be more than C-style arrays in C. Anyway,new
will create you a C-style array if you ask like this:Unfortunately,
delete contents;
will not work even withint (*contents)[10];
. The compiler is allowed to do the right thing: the standard doesn't specify that the array is converted to a pointer as withnew
, and I believe I recall GCC substitutingdelete[]
and emitting a warning. But it's undefined behavior.So, you will need two destructors, one to call
delete
and one to calldelete[]
. Since you can't partially specialize a function, the functionality demands a partially specialized helperwhich for some reason I just subjected myself to ;v)
Unfortunately, this doesn't work with dynamic-sized arrays, so I'm going to write up another answer.
第二次尝试……
让智能指针类对数组变得智能是很容易的。正如您所怀疑的,如果您知道它是一个数组,则不需要构造函数的运行时标志或参数。唯一的问题是
new
和new[]
具有相同的返回类型,因此它们无法将此信息传递给智能指针类。bool
标志的替代方法是重载T[]
的含义,就像访问者提到std::unique_ptr
在 C++0x 中所做的那样。Second attempt…
It's quite easy to make a smart pointer class smart about arrays. As you suspected, you don't need a runtime flag or argument to the constructor if you know it's an array to begin with. The only problem is that
new
andnew[]
have identical return types, so they cannot pass this information to the smart pointer class.An alternative to the
bool
flag is to overload the meaning ofT[]
as Visitor mentionsstd::unique_ptr
does in C++0x.