【问题标题】:WHY does an uninitialised pointer work in C++ programs? [duplicate]为什么未初始化的指针在 C++ 程序中起作用? [复制]
【发布时间】:2015-04-22 20:00:59
【问题描述】:

请检查下面的代码:

class Human
{ 
public:
    void chat(Human h)
    {
        cout << "human";
    }

    void chat(ComputerScientist c)
    {
        cout << "computer";
    }
};

class ComputerScientist : public Human
{
};

//Main function below
int main()
{
    Human* p, p1;
    //Uninitialized pointer above;

    p->chat(p1); //It shows perfectly the result without ANY error!
}

但是,如果我在派生类 ComputerScientist 中创建一个覆盖人类函数的函数,事情就会变得棘手。

class Human
{
public:
    virtual void chat(Human* h)
    {
        cout << "about the weather";
    }

    virtual void chat(ComputerScientist* c)
    {
        cout << "about their own computer illiteracy";
    }
};

class ComputerScientist : public Human
{
public:
    virtual void chat(Human* h)
    {
        cout << " about computer games";
    }

    virtual void chat(ComputerScientist* c)
    {
        cout << " about others’ computer     illiteracy";
    }
};

而且我使用相同的 main 函数,它似乎是空指针行中的分段错误。但为什么呢?

第二个例子中的两个地方发生了变化:

  1. 我通过将其设为虚拟来使用覆盖函数。
  2. 函数将指针作为参数。

【问题讨论】:

  • “C 让你很容易射中自己的脚;C++ 让它更难,但是当你这样做时,它会炸掉你的整条腿。” --- 某人
  • 还要注意在human* p, p1; 中只有p 是一个指针。如果您希望两者都是指针,请使用human *p, *p1;
  • “C 语言让你很容易在脚下开枪”引用stroustrup.com/bs_faq.html#really-say-that

标签: c++ oop computer-architecture


【解决方案1】:

您编写的代码表现出未定义的行为。遇到未定义行为的代码可能:

  • 分段错误
  • 向屏幕输出奇怪的字符。
  • 因优化级别和编译器而异
  • 完全按照您的意愿工作。

【讨论】:

    【解决方案2】:

    在第一种情况下,您的类是一个 POD(普通旧数据),并且您的聊天函数不会取消引用/访问任何成员变量 - 因此它似乎可以正常工作(尽管这是一种不好的做法 - 由于未定义的行为)。在virtual functions each object has vtable 的情况下,它需要一个有效的指针才能工作——因此会导致错误。

    以下是您如何使您的第一个案例错误:

    class Human 
    { 
        private:
            int n;
        public:
    
        void chat(Human h) 
        {
            cout << "human #" << n << endl;
        }
    
        void chat(ComputerScientist c) 
        {
            cout << "computer";
        }
    };
    
    class ComputerScientist:public Human{};
    
    int main()
    {
        Human* p,p1;
        //Uninitialized pointer above;
        p->chat(p1);//It shows perfectly the result without ANY error!
    
        return 0;
    }
    

    【讨论】:

    • 注意:thus it works okay. 是的,这就是它在这种情况下有效的原因,但这并不意味着它是正确的。 OP 所做的是调用一个不以任何方式依赖于 p 或 p1 的函数,因此编译器会生成一个函数调用,而不会对这些变量感兴趣。但这不是必须的。它可能会崩溃(或其他任何东西)
    • 这里要明确一点,it works ok 应该是it happens to work ok this time, it may not next time。未定义的行为是反复无常的事情,应该真正避免。
    • @deviantfan:是的,这种行为是不对的——我的回答更多的是为什么没有段错误。关于编码,这不是应该如何编码,应该在代码审查中标记
    • @Sarang 别担心,我知道你的意思。我的评论更适合 OP 和其他读者。
    • @MikeVine:谢谢-我已经对文本进行了编辑
    猜你喜欢
    • 2012-08-23
    • 1970-01-01
    • 2015-05-01
    • 1970-01-01
    • 2012-02-06
    • 2018-04-22
    • 1970-01-01
    • 2016-03-12
    • 2019-06-18
    相关资源
    最近更新 更多