非常坑!当把对象作为值类型的时候,比如SomeType是SomeSucker的一个值类型
class SomeSucker {
SomeType something;
SomeSucker() {
something = SomeType();
some_method();
}
};
class SomeType() {
int arr[100];
int* ptr;
SomeType() {
ptr = &arr[0];
}
void some_method() {
...
assert(ptr == &arr[0]);
}
};
当我们运行some_method时,会惊奇地发现,ptr != &arr[0] !即使我们已经写了 ptr = &arr[0];
这是为什么呢?
原来,something = SomeType();
在初始化时(等式右边计算时),SomeType()
是一个栈上的临时变量,之后它才被拷贝到something
这个成员变量中,因此第一次运行 ptr = &arr[0];
和之后计算 &arr[0];
,用的arr[0]
不是一个位置上的 arr[0]
,它已经因为拷贝移动了,但是ptr
没有更新。
要解决这个问题,无非两个办法:
直接在声明时构造,记住使用直接构造而不是拷贝构造,cannot risk that
class SomeSucker { SomeType something; SomeSucker(): something(SomeType()) { } };
注意如果不在初始化表中指明something的初始化方式的话,会自动调用其无参构造函数、
找一个合适的实际初始化
ptr
,不要在初始化的时候设定它。
c++ 真是硬核语言!