为什么通过值传递指针并通过其地址传递它们都会调用hello()?
class MyObj
{
public:
void hello()
{
printf("hello");
}
};
void myfunc(void *ptr)
{
// I want the device
MyObj* ptr2 = static_cast<MyObj*>(ptr);
ptr2->hello();
}
int main()
{
MyObj thisobj;
void *pointer_to_device = &thisobj;
myfunc(pointer_to_device);
myfunc(&pointer_to_device);
return 0;
}
&amp; pointer_to_device在做什么?这很奇怪,不应该被允许,该函数不是要求指针指针
我正在使用MSVC2012
答案 0 :(得分:2)
myfunc(&pointer_to_device)
导致未定义的行为。
据推测,它似乎适合您,因为您在通话时或MyObj
内无法访问hello
的任何成员。要证明这一点,请尝试使用更新版MyObj
class MyObj
{
const char* str;
public:
MyObj() : str("hello") {}
void hello()
{
printf("%s\n", str);
}
};
答案 1 :(得分:2)
您的代码显示未定义的行为。
请注意,hello()
是非虚拟类中的非虚方法。编译器将盲目地生成对MyObj::hello()
的方法调用,并使用用于调用的指针中的任何垃圾执行此操作,将其作为此传递。
顺便说一句,当您开始访问“对象”中的成员变量时(首先不是对象),这会变得特别讨厌。
答案 2 :(得分:0)
正在掩盖问题的void * ptr,void *可以接受指向指针的指针。如果用MyObj *替换它,编译器会抱怨。
答案 3 :(得分:0)
对myfunc
的第二次调用有未定义的行为,因为您将void**
转换为MyObj*
然后取消引用它。未定义的行为意味着任何事情都可能发生,包括看似正常工作。
这很奇怪,不应该被允许,该函数不是要求指针指针
它要求void*
这是一个可以指向任何东西的指针,它可以指向MyObj
(在第一种情况下)或者它可以指向另一个void*
(在第二种情况下)这是允许的,你有责任不做那样的事情。如果你不能信任不这样做,那就不要搞砸void*
和演员。
代码看起来有效的原因是您不访问对象的任何成员数据,因此编译器实际上不需要在*ptr2
读取任何内存。你的程序大致相当于此(除了没有未定义的行为):
void hello(MyObj* unused)
{
printf("hello");
}
void myfunc(void *ptr)
{
// I want the device
MyObj* ptr2 = static_cast<MyObj*>(ptr);
hello(ptr2);
}
int main()
{
MyObj thisobj;
void *pointer_to_device = &thisobj;
myfunc(pointer_to_device);
myfunc(&pointer_to_device);
}
注意ptr2
的值从未实际使用过,所以它可以正常工作。在您的版本中,指针在技术上被ptr2->hello()
取消引用,但实际上编译器不需要取消引用该变量来调用成员函数。但它仍然是未定义的行为。