【问题标题】:Is -fno-elide-constructors contained in -O0 or any other optimization level?-fno-elide-constructors 是否包含在 -O0 或任何其他优化级别中?
【发布时间】:2014-01-30 23:20:24
【问题描述】:

-fno-elide-constructors 是否包含在 -O0 或任何其他 -O[其他级别] 中?

在我看来,-fno-elide-constructors 是一个优化标志,-O 是优化级别。因此,某些 -O 级别可能包含标志 -fno-elide-constructors。 我说的对吗?

也就是说-fno-elide-constructors和-O..之间有什么关系吗?

【问题讨论】:

  • 我相信它可以通过优化设置添加,但我不确定是哪一个。

标签: c++ gcc optimization c++11


【解决方案1】:

也就是说,-fno-elide-constructors 之间是否有关系 和-O..?

是的,有一个关系,虽然很简单:gcc 很可能会忽略 -O0 级别的构造函数,除非您明确禁用它。证明见底部示例代码。

这很棘手,编译器可以做一些非常讨厌的事情,请参阅RVO force compilation error on failure。底线是:您始终需要检查生成的程序集以了解幕后实际发生的情况。

请记住(from Working Draft, Standard for Programming Language C++, N3797 这是我能找到的最接近 C++14 的近似值):

12.8/31 当满足某些条件时,允许实现省略类对象的复制/移动构造,即使为复制/移动操作选择的构造函数和/或对象的析构函数有副作用. [...]


证实我的陈述的代码:

#include <cstdio>
constexpr int size = 1024;

struct A { int array[size] = { 0 }; };

int main() {
  A a = A();
  std::printf("%d\n", a.array[size-1]);
}

使用g++ -std=c++11 -Wall -O0 -S elide.cpp,在生成的汇编代码中只有一个

    call    A::A()

但是,g++ -std=c++11 -Wall -O0 -fno-elide-constructors -S elide.cpp 我得到:

    call    A::A()
    [...]
    call    A::A(A&&)

即使您使用-O0 禁用优化,如果您出于某种原因需要禁用它,您仍然必须另外禁用省略。

【讨论】:

  • 关于:Because some compilers do not perform copy elision in every situation where it is allowed, programs that rely on the side-effects of copy/move constructors and destructors are not portable. 这不准确。该行为在标准(C++14 12.8/31 和 /32,甚至 C++98 12.8/15)中有具体描述,因此它是“可移植的”。只是有些编译器会比其他编译器做更多的副本。有点像“long”在某些平台上可以是 32 位,而在其他平台上可以是 64 位。我的猜测是,如果您需要禁用 RVO 以确保您有一些行为,那么您正在做一些可疑的事情..
  • @paercebal 谢谢,已修复!我猜写“便携式”的人意味着如果您切换到另一个编译器,那么可能会发生奇怪的事情...... :( 是的,我完全同意,如果有人依赖这种行为,那就太可疑了。无论如何,更新我的答案,谢谢!
猜你喜欢
  • 1970-01-01
  • 2012-08-27
  • 2015-01-21
  • 1970-01-01
  • 2022-12-14
  • 2020-06-28
  • 1970-01-01
  • 2019-01-01
  • 1970-01-01
相关资源
最近更新 更多