未使用的成员变量会占用内存吗? [英] Does an unused member variable take up memory?

查看:152
本文介绍了未使用的成员变量会占用内存吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Does initializing a member variable and not referencing/using it further take up RAM during runtime, or does the compiler simply ignore that variable?

struct Foo {
    int var1;
    int var2;

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

在上面的示例中,成员'var1'得到一个值,该值然后显示在控制台中.但是,根本不使用"Var2".因此,在运行时将其写入内存将浪费资源.编译器会考虑这种情况,而只是忽略未使用的变量,还是Foo对象总是相同大小,而不管其成员是否被使用?

In the example above, the member 'var1' gets a value which is then displayed in the console. 'Var2', however, is not used at all. Therefore writing it to memory during runtime would be a waste of resources. Does the compiler take these kinds of situations into an account and simply ignore unused variables, or is the Foo object always the same size, regardless of whether its members are used?

推荐答案

黄金C ++作为"规则 1 指出,如果

The golden C++ "as-if" rule1 states that, if the observable behavior of a program doesn't depend on an unused data-member existence, the compiler is allowed to optimized it away.

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

Does an unused member variable take up memory?

否(如果确实"未使用).

No (if it is "really" unused).

现在要记住两个问题:

  1. 可观察的行为何时不取决于成员的存在?
  2. 现实生活程序中会发生这种情况吗?

让我们从一个例子开始.

Let's start with an example.

#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编译此翻译单元,则会输出:

If we ask gcc to compile this translation unit, it outputs:

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做了类似的事情).

f2 is the same as f1, and no memory is ever used to hold an actual Foo2::var2. (Clang does something similar).

有人可能会说这有所不同,原因有两个:

Some may say this is different for two reasons:

  1. 这太琐碎了,
  2. 该结构已完全优化,不算数.

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

Well, a good program is a smart and complex assembly of simple things rather than a simple juxtaposition of complex things. In real life, you write tons of simple functions using simple structures than the compiler optimizes away. For instance:

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

这是未使用数据成员(此处为std::pair<std::set<int>::iterator, bool>::first)的真实示例.你猜怎么了? 已被优化(带有虚拟集的简单示例(如果该程序集让您哭泣).

This is a genuine example of a data-member (here, std::pair<std::set<int>::iterator, bool>::first) being unused. Guess what? It is optimized away (simpler example with a dummy set if that assembly makes you cry).

现在将是阅读Max Langhof出色答案的最佳时机(请为我投票).最终解释了为什么结构的概念在编译器输出的汇编级别没有意义.

Now would be the perfect time to read the excellent answer of Max Langhof (upvote it for me please). It explains why, in the end, the concept of structure doesn't make sense at the assembly level the compiler outputs.

有很多评论认为此答案一定是错误的,因为某些操作(如assert(sizeof(Foo2) == 2*sizeof(int)))会破坏某些内容.

There have been a number of comments arguing this answer must be wrong because some operation (like assert(sizeof(Foo2) == 2*sizeof(int))) would break something.

如果X是程序 2 的可观察行为的一部分,则不允许编译器优化这些内容.对包含未使用"数据成员的对象有很多操作,这会对程序产生明显影响.如果执行了这样的操作,或者如果编译器无法证明没有执行任何操作,则未使用"的数据成员是程序可观察到的行为的一部分,无法优化.

If X is part of the observable behavior of the program2, the compiler is not allowed to optimized things away. There are a lot of operations on an object containing an "unused" data-member which would have an observable effect on the program. If such an operation is performed or if the compiler cannot prove none is performed, that "unused" data-member is part of the observable behavior of the program and cannot be optimized away.

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

Operations that affect the observable behavior include, but are not limited to:

  • 获取某种对象(sizeof(Foo))的大小,
  • 获取在未使用"的数据成员之后声明的数据成员的地址,
  • 使用memcpy
  • 之类的功能复制对象
  • 操纵对象的表示形式(如memcmp一样)
  • 将对象限定为 volatile
  • .
  • taking the size of a type of object (sizeof(Foo)),
  • taking the address of a data member declared after the "unused" one,
  • copying the object with a function like memcpy,
  • manipulating the representation of the object (like with memcmp),
  • qualifying an object as volatile,
  • etc.

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)就像断言是通过还是失败.

2) Like an assert passing or failing is.

这篇关于未使用的成员变量会占用内存吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆