动态指针数组初始化疑问:为何*(clone[toffset])赋值失败而*(clone + toffset)可行?
兄弟,我来给你掰扯清楚这个问题,你这是对指针和数组下标的本质理解有点模糊,咱们一步一步来:
首先先明确你创建的clone是什么:你用new Bitmap*[tiles_x * tiles_y]创建的是一个存储Bitmap指针的数组,数组里的每个元素都是Bitmap*类型的指针变量。clone本身是这个数组的首地址,类型是Bitmap**(指向指针的指针)。
咱们先拆解两种写法的区别:
为什么*(clone[toffset]) = tclone会失败?
clone[toffset]本身就是数组下标运算符的语法糖,它等价于*(clone + toffset)——也就是数组中第toffset个位置的那个Bitmap*指针变量。但问题是,此时这个clone[toffset]指针还完全没有被初始化,是个野指针,它指向的是随机的内存地址。
你在它前面加*,也就是*(clone[toffset]),相当于试图去访问这个野指针指向的「Bitmap对象」,然后把tclone(一个Bitmap指针)赋值给这个对象——这完全是南辕北辙:
- 首先类型不匹配:
*clone[toffset]是Bitmap对象,而tclone是Bitmap*指针,你不能把指针直接赋值给对象; - 更关键的是,这个野指针根本没指向有效的Bitmap对象,甚至可能指向操作系统保护的内存,直接触发访问错误,程序崩溃。
你本来的目的是把tclone这个指针存到数组的对应位置,结果你错误地去修改了这个指针指向的(不存在的)对象,当然会失败。
为什么*(clone + toffset) = tclone是对的?
clone是Bitmap**类型,clone + toffset是一个指向数组第toffset个元素的指针(类型还是Bitmap**)。对它解引用*(clone + toffset),就得到了数组中那个Bitmap*类型的变量——这正是你要赋值的目标!把tclone赋值给它,就是把新创建的Bitmap指针存到数组的对应位置,完全符合你的需求。
而且其实还有更简洁的写法:clone[toffset] = tclone;,这和*(clone + toffset) = tclone是完全等价的,因为数组下标[]就是C++为指针运算提供的语法糖,a[b]等价于*(a + b)。直接写clone[toffset] = tclone可读性更好,没必要写指针加法的形式。
最后给你的整体做法打个分
你的思路是对的:用一维数组模拟二维数组(通过计算offset来定位)是完全合理的写法,没问题。不过有两个小提醒:
- 记得在程序结束或者不需要这些Bitmap对象的时候,一定要遍历数组,逐个
delete每个Bitmap*指针,然后再delete[] clone,否则会造成内存泄漏; - 以后写代码的时候,可以多关注编译器的警告——虽然你说编译没警告,但这种类型不匹配的操作,正常情况下编译器应该会提示你“不能将Bitmap*赋值给Bitmap类型”之类的信息,可能你没开足够的警告等级?可以试试MinGW的
-Wall -Wextra参数,能帮你提前发现很多问题。
内容来源于stack exchange

