C++ 是否可以在不增加包含对象的情况下添加私有成员变量';s码?

C++ 是否可以在不增加包含对象的情况下添加私有成员变量';s码?,c++,sizeof,C++,Sizeof,我有一个名为ObjectCounter的小实用程序类,它没有虚方法和成员变量;它只包含一个构造函数和一个析构函数,分别递增和递减一个全局变量: int _objectCount = 0; // global class ObjectCounter { public: ObjectCounter() {printf("DefaultCtor: count=%i\n", ++_objectCount);} ~ObjectCounter() {printf(&qu

我有一个名为
ObjectCounter
的小实用程序类,它没有虚方法和成员变量;它只包含一个构造函数和一个析构函数,分别递增和递减一个全局变量:

int _objectCount = 0;  // global

class ObjectCounter
{
public:
   ObjectCounter() {printf("DefaultCtor:  count=%i\n", ++_objectCount);}
   ~ObjectCounter() {printf("Dtor:  count=%i\n", --_objectCount);}
};
当我想跟踪我的程序在任何给定时间创建的另一个类的实例数时,我只需向该类添加一个
ObjectCounter
作为私有成员变量:

class SomeUserClass
{
public:
   SomeUserClass() : _userData(0) {/* empty */}
   ~SomeUserClass() {/* empty */}

private:
   ObjectCounter _objectCounter;
   int64_t _userData;
};
(最初我将使用该类的子类
ObjectCounter
,但这样做是在制造,所以我改为将其变成私有成员变量)

今天我注意到,将这个“空”私有成员变量添加到我的类对象中通常会增加类对象的大小(正如sizeof()所报告的)。例如,以下代码显示,当我包含
\u objectCounter
成员变量时,我的计算机上的
sizeof(SomeUserClass)
从8增加到16:

int main(int, char **)
{
   SomeUserClass sc1;
   printf("sizeof(SomeUserClass)=%zu\n", sizeof(SomeUserClass));
   printf("sizeof(ObjectCounter)=%zu\n", sizeof(ObjectCounter));

   return 0;
}
无论是否启用优化(通过
-O3
)都会增加

我认为这是因为编译器正在为
\u objectCounter
成员变量分配空间,这样,如果其他代码需要获取指向objectCounter的指针,就可以提供唯一的地址。但是我的程序中没有任何代码实际引用了
\u objectCounter
变量;它的存在只是为了在适当的时间执行它自己的默认构造函数和析构函数


考虑到这一点,有没有办法鼓励(或者更好的办法是强制)编译器不为此成员变量分配任何空间?

如果可以使用C++20,可以使用该属性来实现这一点。使用

#include <cstdio>
#include <cstdint>

int _objectCount = 0;  // global

class ObjectCounter
{
public:
   ObjectCounter() {printf("DefaultCtor:  count=%i\n", ++_objectCount);}
   ~ObjectCounter() {printf("Dtor:  count=%i\n", --_objectCount);}
};

class SomeUserClass
{
public:
   SomeUserClass() : _userData(0) {/* empty */}
   ~SomeUserClass() {/* empty */}

private:
   [[no_unique_address]] ObjectCounter _objectCounter;
   int64_t _userData;
};

int main(int, char **)
{
   SomeUserClass sc1;
   printf("sizeof(SomeUserClass)=%zu\n", sizeof(SomeUserClass));
   printf("sizeof(ObjectCounter)=%zu\n", sizeof(ObjectCounter));

   return 0;
}

尝试使
int64\t
类成员成为该类的第一个成员。@SamVarshavchik我尝试过它,
sizeof(SomeUserClass)
仍然是16。从
ObjectCounter
继承,以便可以应用空基优化。在大多数情况下都会。切线:将
\u objectCount
从全局变量更改为属于
ObjectCounter
的静态类变量非常简单。简单但需要更多的键入。通过添加复制和移动构造函数,将其更改为遵守3/5/0规则,并根据需要增加计数器。如果您使用的是C++20,则有属性
[[no_unique_address]]
这似乎是一个很好的解决方案,只是当我尝试它时(对于
g++-O3 temp.cpp-std=c++20
,使用XCode 12.5中的Apple clang v12.0.5),
sizeof(SomeUserClass)
即使使用
[[no_unique_address]]也会打印为16
标记已应用。编译器错误,可能?@JeremyFriesner错误,可能还无法实现。MacOS上的IIRC g++实际上是铿锵的,至少铿锵12.0给出了正确的结果:啊,我看到了区别——如果我先声明
\u userData
我得到sizeof=16,但如果我先声明
\u objectCounter
我得到sizeof=8。
DefaultCtor:  count=1
sizeof(SomeUserClass)=8
sizeof(ObjectCounter)=1
Dtor:  count=0