什么是VS C ++编译器应该使用此代码?

时间:2014-11-01 23:14:45

标签: c++ qt visual-studio-2013

这是我今天需要调试的简化代码段。

我意外地输入了这样的内容:

QImage myImage = LoadImage(path);
QImage scaledImage = myImage.scaled(100, 100);
if (condition)
{
   QImage scaledImage = scaledImage.mirrored(true, true); // *** Crash ***
}

而不是意图代码:

QImage myImage = LoadImage(path);
QImage scaledImage = myImage.scaled(100, 100);
if (condition)
{
   scaledImage = scaledImage.mirrored(true, true); // *** Works fine ***
}

我原本期望有缺陷的代码按预期工作或生成编译器错误。但它只是以零除法崩溃。为什么?有人能告诉我编译器关于这个错误的观点吗?

2 个答案:

答案 0 :(得分:3)

想想这行代码的作用:

QImage scaledImage = scaledImage.mirrored(true, true); // Crash
  1. 定义了符号scaledImage。此scaledImage符号名称将覆盖外部作用域中的同名名称。
  2. 调用mirrored()方法。
  3. 现在使用带有mirrored()输出的复制构造函数创建
  4. scaledImage
  5. 正如PeterT在评论中指出的那样,这是未定义的行为:您在创建对象之前调用方法。在这种情况下,崩溃可以帮助您避免容易犯的错误。

    以下是一个示例,详细说明了此问题的存在方式和原因:

    class Tester {
    public:
        Tester() {
            qDebug() << "Default c'tor";
        }
    
        Tester( const Tester& other ) {
            qDebug() << "Copy c'tor";
        }
    
        Tester& Tester::operator=( const Tester& other ) {
            qDebug() << "Assignment";
            return *this;
        }
    
        Tester& test() {
            data = "test";
            return *this;
        }
    };
    
    int main(int argc, char *argv[])
    {
        Q_UNUSED(argc);
        Q_UNUSED(argv);
    
        Tester test = test.test();
        return 0;
    }
    

    该程序将输出以下内容:

      

    测试

         

    复制c&#39; tor

    换句话说,在调用任何构造函数之前调用了test()方法。那太糟糕了!

    但是如果我们用数据成员修改我们的例子会更糟糕:

    class Tester {
        QString data;
    public:
        Tester() {
            qDebug() << "Default c'tor";
            data = "data";
        }
    
        Tester( const Tester& other ) {
            qDebug() << "Copy c'tor";
            data = other.data;
        }
    
        Tester& Tester::operator=( const Tester& other ) {
            qDebug() << "Assignment";
            data = other.data;
            return *this;
        }
    
        Tester& test() {
            data = "test";
            qDebug() << "Test";
            return *this;
        }
    
    };
    

    现在程序在打印出任何内容之前崩溃了。具体来说,test()中的第一行是罪魁祸首:

    data = "test";
    

    如果您考虑一下,这就是尝试将某些内容分配给尚未构建的QString。任何访问或修改未构造对象的成员变量的尝试都是坏消息。

答案 1 :(得分:1)

如果您减少此代码,原因仍然存在。

此:

QImage myImage = LoadImage(path);
QImage scaledImage = myImage.scaled(100, 100);
if (condition)
{
   QImage scaledImage = scaledImage.mirrored(true, true); // *** Crash ***
}

与此有相同的错误:

QImage myImage = LoadImage(path);
QImage scaledImage = scaledImage.mirrored(true, true); // *** Crash ***

因为右侧的scaledImage从左侧调用未初始化对象上的函数。这是未定义的行为。