#include <iostream>
char** make2D(const int dim1, const int dim2)
{
char* toAlloc;
const int size = (dim1 * dim2) + dim2;
toAlloc = new char[size];
for(int i = 0; i < dim2; i++)
{
toAlloc[i] = reinterpret_cast<char>(&toAlloc[(dim2 + (dim1 * i))]);
}
return reinterpret_cast<char**>(toAlloc);
}
int main(void)
{
int dim1 = 8;
int dim2 = 10;
char** array2D = make2D(dim1, dim2);
for (int i = 0; i < dim2; ++i)
{
array2D[i][i % dim1] = i + 100; // << Crash
}
return 0;
}
我试图通过一次分配来分配二维数组。
因此,我的算法是,前10个(在此代码中为dim2
)具有指向每行第一项的指针。
当我尝试通过指向“ int”的指针进行尝试时,
int** make2D(const int dim1, const int dim2)
{
int* toAlloc;
const int size = (dim1 * dim2) + dim2;
toAlloc = new int[size];
for(int i = 0; i < dim2; i++)
{
toAlloc[i] = reinterpret_cast<int>(&toAlloc[(dim2 + (dim1 * i))]);
}
return reinterpret_cast<int**>(toAlloc);
}
int main(void)
{
int dim1 = 8;
int dim2 = 10;
int** array2D = make2D(dim1, dim2);
for (int i = 0; i < dim2; ++i)
{
array2D[i][i % dim1] = i + 100;
}
return 0;
}
它工作正常,但是当我在char中执行此操作时,它在上面的代码的注释行中崩溃。
我想到崩溃的原因是当我执行reinterpret_cast
时,由于指针(8字节)和char(1字节)之间的内存大小差异而发生了某些事情。
听起来像是荒谬的...将指针(8byte)更改为int(4byte)很好,但是当我进行更显着的转换(8byte至1byte)时,会引起一些问题...
我不知道为什么char不起作用而int起作用。 您能否提出一些建议使字符案例有效?
答案 0 :(得分:0)
要回答这个问题,是的,有一个很大的区别,在许多平台上,指针可能适合一个int,而在很少的平台上,它将适合一个char。在现代的64位PC上,没有一种存储指针的安全方法。
如果大小是静态的,请使用诸如vector或array之类的容器。 尝试类似的东西:
array<array<T, dim2>, dim1> variable{};
如果您实际上想要类型T的二维数组;由于您似乎需要一个指针数组,因此请尝试以下操作:
array<array<T *, dim2>, dim1> variable{};
这将确保为您的平台创建一个适当类型的数组以存储指针,无论实际上有多大指针,显然,您都应该用要指向的数据的适当类型替换T,这将确保为您正确完成指针数学运算。 数组类型的大小将在编译时计算,如果需要动态大小,则应在向量和所有子向量的分配调用resize之后使用向量,以确保您分配所有内存的次数尽可能少可能。
也请不要使用reinterpret_cast或C样式强制转换,除非您非常了解自己在做什么,否则这是灾难的秘诀。
不知道您正在读什么书或谁在教您C ++,但请更改您的知识来源。
不鼓励使用原始拥有的指针,并且您使用它们的方式在很多方面都是错误的。 除指针类型外,切勿将指针存储在其他任何东西中。即使在普通C语言中,如果需要完全转换,也应至少转换为void *。
如果您真的想直接存储/传递指针,请阅读有关unique_ptr或shared_ptr的信息。
如果您坚持对容器使用原始指针,请尝试使用诸如地址清理器,内存清理器(至少clang和gcc支持这些清理器,如今可能还会有更多的编译器)之类的清理器来构建代码。
答案 1 :(得分:0)
问题是对象大小的“不兼容”:
sizeof(char)
是1
sizeof(int)
通常是4
或8
(但至少是2
)。sizeof(T*)
(通常为4
或8
,std::uintp_t
可以保存void*
的值,而对于int
则不必这样(甚至更少,char
)。您不能将void*
安全地存储到char
或int
中。碰巧它可以为您int
使用,但它不可移植。
reinterpret_cast
通常是错误的工具。
更简单的方法是创建一个class Matrix
,并使用std::vector<T>
和访问器来修复索引。 (您甚至可以使用代理来允许m[2][3]
语法)。
拥有原始指针后,您需要新的展示位置,并提供正确的删除器...