当您在堆栈上有一个指向对象的非静态成员函数的指针时,当对象因为移动而改变其位置时,究竟会发生什么? 指针是否仍然指向移出对象的位置,因此是无效的/悬空的?
指向成员函数的指针不包含对类的任何实例的引用。 即使对于指向非静态成员函数的指针也是如此。
这样的指针可以在没有类实例的情况下构造:
class star {
public:
void shine();
};
void (star::* smile)() = &sun::shine;
并且在调用实例时需要指定实例:
star sun;
(sun.*smile)();
std::memfn(smile)(sun);
一个对象不会“改变它的位置”。 当移动发生时,使用某种未指定的机制(由对象的move构造函数或move赋值运算符控制)将被移动的对象的状态转移到被移动到的对象。 要从中移动的对象继续正常存在,处于某种有效但未指定的状态。
一个简单的例子是std::vector
。 std::vector
的移动语义的经典实现涉及交换内部指针和向量内容的大小。 在处理结束时,moved-from向量是有效的std::vector
,其中包含moved-to向量的内容(moved-to向量包含moved-from向量的内容)。
如果您有指向moved-from对象的指针,则该指针仍然指向该对象,处于某种有效但未指定的状态。 这种情况一直存在,直到被移动的对象被实际破坏。 如果对象在自动作用域中,当执行线程带着自动对象离开作用域时,通常会发生这种情况。 当这种情况发生时,就会留下一个悬空的指针,这与任何其他情况下留下一个指向不再存在的对象的悬空指针没有什么不同。
当您有指向堆栈上对象的非静态成员函数的指针时,
不能有指向特定对象成员函数的指针。 以下内容无效,不会编译:
struct obj {
void f();
};
void func()
{
obj o;
using func_ptr = void (obj::*)();
f_ptr pointer_to_o_f = &o::f; // Error
}