0

我错误地写了一些愚蠢的东西,令我惊讶的是,它奏效了。

class A
{    public:
        void print()
        {
            std::cout << "You can't/won't see me !!!" << std::endl;
        }  
        A* get_me_the_current_object()
        {
            return this;
        }
};  
int main()
{
    A* abc = dynamic_cast<A*>(abc);
    abc->print();
}

在这里,A* abc = dynamic_cast<A*>(abc)我正在对未声明的指针执行 dynamic_cast。但是,它有效,所以我假设上述语句被破坏为:

A* abc;
abc = dynamic_cast<A*>(abc);

因此,它有效。但是,在尝试一些更奇怪的场景时,例如:

A* abc;
abc->print();

并进一步

A* abc = abc->get_me_the_current_object(); 
abc->print();

看着这些例子是如何工作的,映射是如何完成的,我大吃一惊。
有人可以详细说明这些是如何工作的吗?提前致谢。

4

2 回答 2

6

您犯了一个常见的错误,即认为未定义的行为和 C++ 错误意味着您应该预期会看到严重的崩溃或计算机着火。有时什么也不会发生。这并不意味着代码“有效”,因为它仍然有一个错误,只是症状还没有出​​现……还没有

但是,它有效,所以我假设上述语句被破坏为:

是的,您所做的只是将未初始化的指针转换为相同的类型,即不需要转换,因此编译器什么也不做。您的指针仍然是相同的类型,并且仍未初始化。

这与此类似:

int i = i;

根据 C++ 的语法,这是有效的,因为i此时在范围内,但未定义,因为它复制了一个未初始化的对象。但是,它实际上不太可能使您的计算机着火,它似乎“工作”。

有人可以详细说明这些是如何工作的吗?

从技术上讲,您正在取消引用无效指针,这是未定义的行为,但由于您的成员函数实际上并未使用对象的任何成员,因此不会取消引用无效this指针,因此代码“有效”(或至少看起来如此。 )

这类似于:

void function(A* that)
{
    std::cout << "Hello, world!\n";
}
A* p;
function(p);

因为that没有使用指针(就像this在你的成员函数中没有使用指针),这不一定会崩溃,尽管它可能会在复制未初始化的指针可能导致硬件故障的实现中发生。在您的示例中,您的编译器似乎不需要取消引用abc来调用非静态成员函数,并且将其作为隐藏this参数传递不会导致硬件故障,但即使它没有失败,行为仍然是未定义的以明显的方式,例如段错误..

于 2013-03-06T14:42:42.727 回答
3

abc未初始化并指向内存中未定义的位置,但您的方法不会从中读取任何内容,*this因此它们不会崩溃。

他们不会崩溃的事实几乎可以肯定是实现定义的行为。

于 2013-03-06T14:42:13.433 回答