我一直试图区分传递给构造函数的参数是数组或简单指针的情况。所以,我写这个示例代码
#include <iostream>
#include <type_traits>
using std::cout;
using std::endl;
// here I create a structure which I intend to use
// to tell arrays from non-arrays.
template<typename T>
struct TypeTraits {
static bool const IsArray = false;
};
template<typename T>
struct TypeTraits<T[]> {
static bool const IsArray = true;
};
// And here I create a container to store a pointer.
template<typename TValue>
class Ptr_container {
TValue * ptr;
public:
template<typename T>
explicit Ptr_container(T from_ptr) :
ptr (from_ptr)
{
cout << std::boolalpha;
cout << TypeTraits<T>::IsArray << endl;
cout << "Just to be sure: " << std::is_array<T>::value << endl;
}
~Ptr_container()
{
delete ptr;
}
};
int main () {
Ptr_container<int> a (new int(2));
Ptr_container<int> b (new int[2]);
return 0;
}
结果是假/假。所以,我显然做错了,问题是,我应该做些什么来区分使用 new T 和 new T [N] 分配新内存时的情况?
更新:我已使用std::is_array
添加了“数组”检查,但不会更改结果。
必须有一些方法可以在编译时检测“数组”,因为以下内容:boost::shared_ptr
将指针作为构造函数的参数,并且仅使用该信息以某种方式初始化其内部结构。在boost::shared_ptr
类中的某个位置,有一个结构决定如何删除shared_ptr
指向的内存(使用delete
或delete[]
)。
实际上,我正在尝试实现shared_ptr
的某些部分,但我在阵列识别阶段失败了。
更新2 我终于搞清楚了,所以我正在结束这个问题。该问题的解决方案是向模板添加另一个参数,并以
的方式进行容器的初始化Ptr_container<int, PointerProperty> pa (new int(4));
Ptr_container<int, ArrayProperty> pv (new int[4]);
答案 0 :(得分:1)
Zeta 在评论中说:
typeof (new int) == typeof (new int[]) == int *
但是,如果您需要区分使用new
和new[]
,重载创建的类的对象,那么这些运算符会更有意义。
答案 1 :(得分:1)
你无法区分编译时从new
和new[]
返回的指针。不使用模板,或使用编译器挂钩的标准类型特征,而不使用任何其他技术。
原因应该是显而易见的;如果不是,请考虑以下代码:(事情不会像这样;我只是按照你的例子。)
int * p = nullptr;
if (rand() % 2 == 0)
p = new int;
else
p = new int [42];
print_is_array (p); // Assume this does the detection and prints something.
您(和编译器)如何在编译时知道是p
是使用new
还是new[]
分配的?
此外,你所谓的“数组”更恰当地称为“ vector ”(不要与std::vector
混淆。)数组有一些编译时属性(如大小)运行时分配的内存块不会,即使您碰巧在其中构造多个对象(例如,使用new[]
。)
并且,将T
s(一个真实的,正确的编译时数组)数组传递给接受T *
s的函数将“衰减”类型并失去“阵列”。我在这里指的是你定义构造函数的方式,即它采用T *
。
如果您想知道如何在编译时检测(正确)数组,请查看std::is_array<T>
标题中<type_traits>
模板的实现。
int a [42];
不是这个:
int * p = new int [42];
这是两种不同的类型,但第一种可以“衰变”并隐式地转换为第二种类型。