c++ - 未使用的成员变量是否占用内存?

标签 c++ memory struct

在运行时初始化成员变量而不引用/使用它会进一步占用 RAM,还是编译器只是忽略该变量?

struct Foo {
    int var1;
    int var2;

    Foo() { var1 = 5; std::cout << var1; }
};

在上面的示例中,成员 'var1' 获取一个值,然后将其显示在控制台中。但是,根本不使用“Var2”。因此,在运行时将其写入内存会浪费资源。编译器是否考虑到这些情况并简单地忽略未使用的变量,或者 Foo 对象总是相同的大小,而不管其成员是否被使用?

最佳答案

黄金 C++“假设”规则1 指出,如果 observable behavior的程序不依赖于未使用的数据成员的存在,允许编译器对其进行优化

Does an unused member variable take up memory?

否(如果它“真的”未使用)。


现在想到两个问题:

  1. 什么时候可观察到的行为不依赖于成员的存在?
  2. 现实生活中会不会出现这种情况?

让我们从一个例子开始。

示例

#include <iostream>

struct Foo1
{ int var1 = 5;           Foo1() { std::cout << var1; } };

struct Foo2
{ int var1 = 5; int var2; Foo2() { std::cout << var1; } };

void f1() { (void) Foo1{}; }
void f2() { (void) Foo2{}; }

如果我们问 gcc to compile this translation unit ,它输出:

f1():
        mov     esi, 5
        mov     edi, OFFSET FLAT:_ZSt4cout
        jmp     std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
f2():
        jmp     f1()

f2f1 相同, 并且没有使用内存来保存实际的 Foo2::var2 . (Clang does something similar)。

讨论

有些人可能会说这有两个不同的原因:

  1. 这个例子太琐碎了,
  2. 结构已完全优化,不算数。

嗯,一个好的程序是简单事物的智能和复杂组合,而不是复杂事物的简单并置。在现实生活中,您使用比编译器优化的简单结构编写大量简单函数。例如:

bool insert(std::set<int>& set, int value)
{
    return set.insert(value).second;
}

这是未使用数据成员(此处为 std::pair<std::set<int>::iterator, bool>::first)的真实示例。你猜怎么着? It is optimized away (simpler example with a dummy set 如果那个程序集让你哭了)。

现在是 read the excellent answer of Max Langhof 的最佳时机(请为我投票)。它最终解释了为什么结构的概念在编译器输出的汇编级别上没有意义。

“但是,如果我做 X,未使用的成员被优化掉的事实是个问题!”

有许多评论认为这个答案一定是错误的,因为某些操作(如 assert(sizeof(Foo2) == 2*sizeof(int)) )会破坏某些东西。

如果 X 是程序可观察行为的一部分2,则不允许编译器将其优化掉。对包含“未使用”数据成员的对象有很多操作,这将对程序产生可观察到的影响。如果执行了此类操作,或者编译器无法证明没有执行任何操作,则“未使用”数据成员是程序可观察行为的一部分并且无法优化

影响可观察行为的操作包括但不限于:

  • 获取某类对象的大小 (sizeof(Foo)),
  • 获取在“未使用”之后声明的数据成员的地址,
  • 使用 memcpy 之类的函数复制对象,
  • 操纵对象的表示(如 memcmp ),
  • 将对象限定为 volatile,

1)

[intro.abstract]/1

The semantic descriptions in this document define a parameterized nondeterministic abstract machine. This document places no requirement on the structure of conforming implementations. In particular, they need not copy or emulate the structure of the abstract machine. Rather, conforming implementations are required to emulate (only) the observable behavior of the abstract machine as explained below.

2) 就像断言通过或失败一样。

关于c++ - 未使用的成员变量是否占用内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55060820/

相关文章:

c++ - 是否可以在 googletest 的 Predicate Formatter 中使用 ASSERT_NEAR

c++ - 为什么我们使用函数原型(prototype)?

c++ - 在内核函数中创建对象时发生 CUDA 内存访问冲突

汇编语言 st 和 ld

c - 堆对象的指定初始化器

golang 使用结构本身为 sync.Mutex 和 sync.Cond 初始化成员

c++ - OS X 上缺少 Boost 调试符号

c++ - OSX、VideoToolbox、压缩 session

memory - Angular2 一个非常大的 SPA 内存消耗

c - 在结构中声明 int 数组