我知道这个问题可能会以多种不同的方式提出,但我加入了自己的问题,因为这对我来说仍然不清楚。
考虑以下代码:
long double q = 1.2;
long double &p = q;
cout << sizeof(p) << endl;`
long double
在我的机器上是12个字节,代码的输出符合预期12,因为标准说:
当应用于引用或引用类型时,结果为 引用类型的大小。 (ISO C ++ $ 5.3.3 / 2)
但是你很可能都知道,参考实现是免费的,因此,正如标准所说:
未指明引用是否需要存储(3.7)。
所以看来明天我可以提出我自己的引用实现,需要200个字节,并确保sizeof
运算符返回正确的对象大小(而不是返回我的真实实现大小)参考)
所以我的问题实际上非常简单:
我们可以依赖sizeof
运算符来返回包含类的实际内存占用,特别是引用成员吗?
答案 0 :(得分:6)
比较和对比:
struct container {
long double& dbl;
};
std::cout << sizeof(container::dbl) << '\n';
std::cout << sizeof(container) << '\n';
一行告诉您引用对象的大小。另一个告诉你包含引用的结构的大小。
这种行为不是偶然的。它是由标准定义的,是的,你可以依赖它。
这个问题背后似乎有一个假设,即带有引用或引用类型的sizeof
运算符的行为在某种程度上是任意的和常规的。事实并非如此;它不符合通常适用于参考文献的相同逻辑。
如果我有
long double dbl;
然后在其范围内使用dbl
是左值,也就是说引用。这是必要的,以便可以将值赋给dbl
。因此,dbl
的类型(例如decltype(dbl)
所显示的)是long double&
,而不是long double
。
sizeof(dbl)
返回引用本身的大小而不是引用对象的大小是荒谬的。
一旦你将参考文献放入一个结构中,就会有一个完全不同的野兽。 作为对象的一部分,引用会占用空间,除非可以优化掉包含它的整个对象,否则无法对其进行优化。
答案 1 :(得分:0)
如果您怀疑是否可以依赖以下类型的sizeof
:
struct A
{
int& r;
};
然后是 - 您可以在包含引用的结构中依赖sizeof
。
E.g。这段代码是安全的:
char* buffer = new char[sizeof(A)];
int value;
A* valueRef = new (buffer) A{value};
缓冲区中有足够的字节来存储A对象。
答案 2 :(得分:0)
struct S {
long double& d;
};
static_assert(sizeof(S::d) == sizeof(long double));
static_assert(sizeof(S) != sizeof(S::d)); // true on most platforms
编译器非常聪明,可以知道S
的大小,它不会混淆并认为它是sizeof(S::d)
,因为那将是愚蠢的。