可以在C ++中优化未使用的数据成员

时间:2014-04-19 23:02:12

标签: c++ memory

我有一个C ++类,它有一个私有的未使用的char[]严格来为类添加填充,以防止在共享数组中使用该类时的错误共享。我的问题是双重的:

  1. 在某些情况下,编译器是否可以优化此数据成员?

  2. 当我使用private field * not used进行编译时,如何使-Wall警告静音?最好不要明确地使警告静音,因为我仍然希望在其他地方捕捉到这个问题的实例。

  3. 我写了一个小测试来检查我的编译器,似乎该成员没有被删除,但我想知道标准是否允许这种优化。

    padding.cc

    #include <iostream>
    
    class A {
     public:
      int a_ {0};
    
     private:
      char padding_[64];
    };
    
    int main() {
      std::cout << sizeof(A) << std::endl;
      return 0;
    }
    

    汇编

    $ clang++ --version
    clang version 3.3 (tags/RELEASE_33/final)
    Target: x86_64-unknown-linux-gnu
    Thread model: posix
    
    $ clang++ -std=c++11 -O3 -Wall padding.cc
    padding.cc:8:8: warning: private field 'padding_' is not used [-Wunused-private-field]
      char padding_[64];
           ^
    1 warning generated.
    
    $ ./a.out 
    68
    

3 个答案:

答案 0 :(得分:3)

我不知道编译器优化,但您可以通过两种方式摆脱警告:使用编译指示:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-private-field"
class A{
//...
};
#pragma clang diagnostic pop

或者,它可能更适合您,在您的班级中包含假朋友功能:

class A{
friend void i_do_not_exist();
//... 
};

这样,编译器无法知道该字段是否被使用。因此,它不会抱怨,绝对不会抛出任何东西。如果在任何地方定义了i_do_not_exist()函数,这可能会导致安全问题,因为该函数可以直接访问类的私有成员。

第三种解决方案是定义一个访问padding_成员的虚函数:

class A {
 private:
  void ignore_padding__() { padding_[0] = 0; }
  //... 
};

答案 1 :(得分:1)

我非常确定编译器不允许重新排序或删除数据成员,因此.h文件可以自行记录编写接受此类结构的API的任何人。他们只允许使用简单且定义明确的填充规则,因此开发人员可以通过阅读代码轻松推断出偏移量。

那就是说,为什么要对缓存大小和错误共享的可能性做出假设?缓存大小应该是编译器的责任,我怀疑真正的问题是尝试在多个线程之间共享一个数组。在每个线程上本地更新结构,并在最后只写出对共享数组的更改。

答案 2 :(得分:0)

编译器可以执行符合程序无法检测到的任何更改。所以答案是肯定的。但是,使编码变得更糟的编译器是一个糟糕的编译器。可能的是,你没有使用糟糕的编译器。