可能重复:
何时在空实例上调用成员函数会导致未定义的行为?
这个问题中的人未能使用“new”创建指向对象的指针,然后使用这个野指针调用对象上的成员函数。
访问成员变量时程序失败 (at myPoint[i].x = xData;
)。
为什么它在那个位置失败而不是更早?
可能重复:
何时在空实例上调用成员函数会导致未定义的行为?
这个问题中的人未能使用“new”创建指向对象的指针,然后使用这个野指针调用对象上的成员函数。
访问成员变量时程序失败 (at myPoint[i].x = xData;
)。
为什么它在那个位置失败而不是更早?
this
有问题的行是引用的第一个位置。
那么为何不?标准说这个程序有未定义的行为,但在 C++ 中,我们在一个类中有 3 种函数:
// 1) static functions
class test {
public:
static void foo( int n );
};
在这个例子foo
中就像一个具有相同签名的全局函数,但是 C++ 有不同的访问检查规则和它的名称。
// 2) normal member functions
class test {
public:
void foo( int n );
};
在几乎所有编译器中,此函数与带有签名的自由函数相同,除非您在函数中访问在这种情况下函数可能会产生分段错误或更糟糕的是,更改一些意外点,否则void foo(foo* this, int n)
使用无效调用此函数并不是错误你的记忆。this
this
// 3) virtual functions
class test {
public:
virtual void foo( int n );
};
在这种情况下class test
,包含一个额外的不可见成员,该成员通常被调用vtable
并包含一个指向virtual
类的每个函数的实现的指针,并且使用这种技术 C++ 可以在运行时进行后期绑定,所以在这种情况下,当你调用foo
编译器时,编写类似
this->vtable[foo_index]( this, n );
所以在这种情况下,无效this
会立即显示出来,并且可能会产生诸如分段错误或无效指令之类的错误,因为您this
是在调用点访问的。因此,正如您在几乎所有实现中看到的那样,您可以拥有一个通过无效this
指针调用的成员函数并且永远不会产生任何错误(如果您从未this
在函数中访问),但它不能是virtual
.
但是请记住上面解释的内容完全取决于您的编译器,但几乎所有编译器都像上面那样实现它。
您应该阅读有关未定义行为的更多信息并以示例为基础:
struct A { A(int i): _i(i) {} void print() const { printf("%d", _i); } int _i; };
void function(A* a) {
if (a == 0) { printf("%s", "A is null!"); }
a->print();
}
你期待function(0);
什么?
好吧,您似乎期望它A is null!
会被打印出来,然后程序会崩溃,对吗?也许……也许不是。
编译器实际上可能会这样进行:
a->print();
:a
不能在null
这里,否则这个语句没有意义a == 0
因此总是false
void function(A* a) { a->print(); }
然后,在一个普通的 Linux 平台上,你会得到你的崩溃(SEGFAULT),但没有任何消息......根本!
这就是未定义行为对优化的影响:您的程序运行得更快,但在最轻微的错误中以深不可测的方式死亡。