【问题标题】:Is C++ compiler allowed to optimize out unreferenced local objects是否允许 C++ 编译器优化未引用的本地对象
【发布时间】:2015-02-28 18:11:08
【问题描述】:

我使用以下类在某个函数的开头自动设置等待光标,并在函数返回时重置光标。

class WaitCursorSetter
{
public:
    WaitCursorSetter() {QApplication::setOverrideCursor(Qt::WaitCursor);}
    virtual ~WaitCursorSetter() {QApplication::restoreOverrideCursor();}
};

我在函数开始时创建了一个本地 WaitCursorSetter 对象。由于等待游标在对象的析构函数中被重置,因此我不必在方法中的每个返回语句之前重置游标,因为当函数返回并且对象超出范围时会调用析构函数。

如果编译器优化了未引用的WaitCursorSetter 对象,这将不起作用。我的问题是,允许编译器优化这个对象吗?

【问题讨论】:

    标签: c++ qt optimization


    【解决方案1】:

    不允许编译器优化掉析构函数或初始化有副作用的自动对象,我们可以通过草案标准部分3.7.3看到这一点:

    如果具有自动存储持续时间的变量具有初始化或 带有副作用的析构函数,在结束前不得销毁 它的块,也不应该作为优化被淘汰,即使它 似乎未使用,除了类对象或其复制/移动可能 按照 12.8 的规定被淘汰。

    【讨论】:

      【解决方案2】:

      这样做是绝对安全的。事实上,这是在实践 RAII 时经常使用的技术。编译器不会优化任何具有 non-trivial 构造函数或析构函数的局部变量。查看What is a non-trivial constructor in C++

      为了避免编译器警告未使用的局部变量,您可以使用 Q_UNUSED 宏。

      【讨论】:

        【解决方案3】:

        如果您可以观察到任何不同,则不允许编译器删除该对象。

        在这种情况下构造函数/析构函数有副作用,所以编译器不会删除它们。

        经常使用将效果委托给本地基于堆栈的对象的构造/销毁的想法;例如:

        {
            Locker L(my_lock);
            ...
        }
        

        这样... 中的代码将在持有锁的情况下执行,当您出于任何原因离开作用域时锁将自动释放(刚离开块,执行return 或和如果在里面抛出异常)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-12-30
          • 2021-03-19
          • 1970-01-01
          • 2019-04-21
          • 1970-01-01
          • 2020-02-13
          • 2017-05-04
          相关资源
          最近更新 更多