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

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

  2. 当我用-Wall编译时,如何使private field * not used静音private field * not used警告? 优选地,没有明确地使警告静音,因为我仍然希望在其他地方捕获该问题的实例。

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

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

===============>>#1 票数: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; }
  //... 
};

===============>>#2 票数:1

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

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

===============>>#3 票数:0

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

  ask by Cookyt translate from so

未解决问题?本站智能推荐:

2回复

为什么C ++中类的大小取决于数据成员的公共/私有状态?

据我所知,C ++中类的大小取决于以下因素: 所有非静态数据成员的大小。 数据成员的顺序。 是否启用字节填充。 其直接基类的大小。 虚拟功能的存在。 继承方式(虚拟继承)。 现在,我创建了两个类,如下所示: 现在检查A和BI的大小
3回复

对象数据成员的C ++连续内存访问

我很好奇内存模型如何用于C ++类。 具体来说,是否可以保证对象的数据成员是连续分配的。 例如,如果我有以下代码: class Particle { public: Particle(double ix, double iy, double ivx, double ivy); //
6回复

未使用的成员变量会占用内存吗?

初始化成员变量而不引用或使用它会在运行时进一步占用RAM,还是编译器只是忽略该变量? 在上面的示例中,成员'var1'得到一个值,该值然后显示在控制台中。 但是,根本不使用“ Var2”。 因此,在运行时将其写入内存将浪费资源。 编译器会考虑这种情况,而只是忽略未使用的变量,还是F
4回复

在C ++中优化类实例的内存布局

将应用程序从32位升级到64位会增加指针大小和对象的内存占用量。 我正在寻找尽可能减少对象内存占用的方法。 对于POD结构,我转储结构的内存布局,以找出如何打包成员并减少编译器填充。 有没有办法找出非POD对象的内存布局,如类实例? 我怎么能实现类包装类对象的东西? 谢谢,
8回复

如何在C ++中释放静态成员变量?

任何人都可以解释如何释放静态成员变量的内存吗? 根据我的理解,只有在类的所有实例都被销毁时才能释放它。 此时我有点无助...... 一些代码来解释它:
3回复

在C ++中为指针成员释放动态内存

我有一堂课: 然后我有另一堂课: 我想做的是这样的: 我知道由于class B的构造函数中的new A()而面临内存泄漏的问题。 因此,我试图在每次while循环之后获取释放内存的帮助,这意味着要回收vec_b和向量中所有B类对象占用的所有内存,最重要的是释放占用的内存
2回复

类的内存是否比C ++中的成员大?

假设我有一些类,其中唯一的成员是int。 如果它不在类中,那么int就是4个字节。 该类是否占用超过4个字节的内存(在C ++中)?
1回复

是否可以使用ADODB :: _ RecordsetPtr对象作为成员数据?

我正在写C ++中的类。 这是我的代码: 问题是,当我尝试将临时ADODB::_ConnectionPtr对象分配给pConn ,编译器将引发异常: Unhandled exception at at 0x75C9C41F in AccessReader.exe: Microsoft
1回复

内存中类成员函数的C ++表示[重复]

这个问题已经在这里有了答案: 对象的成员函数存储在哪里? 2个答案 假设我有以下课程: 如果我实例化此类的两个对象,内存中的func()代码是否会重复? 还是func()对于该类的所有对象仅出现一次? 如果没有实例化对象,func()是否会出现在内存中
1回复

存储在共享内存中的C ++对象(volatile成员函数?)

我想知道使用存储在共享内存中的对象的好习惯。 我心中的选择是: 将volatile添加到存储在共享内存中的对象的每个成员函数 在每次迭代时从/向共享内存复制整个数据。 访问没有volatile的共享内存。 让我解释一下我遇到的问题: 我在Linux上运行