简体   繁体   English

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

[英]Can unused data members be optimized out in C++

I have a C++ class which has a private unused char[] strictly to add padding to the class to prevent false sharing when the class is used in a shared array. 我有一个C ++类,它有一个私有的未使用的char[]严格地为类添加填充以防止在共享数组中使用该类时的错误共享。 My question is 2-fold: 我的问题是双重的:

  1. Can this data member be optimized out by the compiler in some circumstances? 在某些情况下,编译器是否可以优化此数据成员?

  2. How can I silence the private field * not used warnings when I compile with -Wall ? 当我用-Wall编译时,如何使private field * not used静音private field * not used警告? Preferably, without explicitly silencing the warning as I still want to catch instances of this issue elsewhere. 优选地,没有明确地使警告静音,因为我仍然希望在其他地方捕获该问题的实例。

I wrote a little test to check for my compiler, and it seems that the member isn't removed, but I want to know if the standards allow this sort of optimization. 我写了一个小测试来检查我的编译器,似乎该成员没有删除,但我想知道标准是否允许这种优化。

padding.cc padding.cc

#include <iostream>

class A {
 public:
  int a_ {0};

 private:
  char padding_[64];
};

int main() {
  std::cout << sizeof(A) << std::endl;
  return 0;
}

compilation 汇编

$ 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

I don't know about the compiler optimizations, but you can get rid of the warnings in two ways: Either use pragmas: 我不知道编译器优化,但您可以通过两种方式消除警告:使用编译指示:

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

or, which is probably better suited for you, include a fake friend function in your class: 或者,它可能更适合您,在您的班级中包含假朋友功能:

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

In that way, the compiler cannot know if the field is used or not. 这样,编译器无法知道该字段是否被使用。 Therefore, it does not complain and will definitely not throw anything out. 因此,它不会抱怨,绝对不会抛出任何东西。 This can lead to safety issues if the i_do_not_exist() function is ever defined anywhere, as that function is given direct access to the private members of the class. 如果在任何地方定义了i_do_not_exist()函数,这可能会导致安全问题,因为该函数可以直接访问类的私有成员。

A third solution is to define a dummy function which access the padding_ member: 第三种解决方案是定义一个访问padding_成员的虚函数:

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

I'm pretty sure compilers aren't allowed to reorder or remove data members, so the .h files are self-documenting for anyone writing an API that accepts such a struct. 我非常确定编译器不允许重新排序或删除数据成员,因此.h文件可以自行记录任何编写接受此类结构的API的人。 They're only allowed to use simple and well-defined padding rules so developers can easily infer the offsets just from reading the code. 它们只允许使用简单且定义明确的填充规则,因此开发人员可以通过阅读代码轻松推断出偏移量。

That said, why are you making assumptions on the cache size and the likelihood of false sharing? 也就是说,为什么要对缓存大小和错误共享的可能性做出假设? The cache size should be the compiler's responsibility, and I suspect the real issue is trying to share an array between multiple threads. 缓存大小应该是编译器的责任,我怀疑真正的问题是尝试在多个线程之间共享一个数组。 Update the struct locally on each thread and only write out the changes to the shared array at the end. 在每个线程上本地更新结构,并在结尾处仅写出对共享数组的更改。

The compiler can perform any change that can't be detected by a conforming program. 编译器可以执行符合程序无法检测到的任何更改。 So the answer is yes. 所以答案是肯定的。 But a compiler that makes changes that make your code worse is a lousy compiler. 但是,使编码变得更糟的编译器是一个糟糕的编译器。 Odds are, you aren't using a lousy compiler. 可能的是,你没有使用糟糕的编译器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM