简体   繁体   English

C ++-const参数和类变量是否被简化?

[英]C++ - Are const parameters and class variables pessimization?

I'm trying to figure out when const should be used when writing C++ code. 我试图弄清楚编写C ++代码时应何时使用const。 Are these all examples of pessimization or is it beneficial to write code this way?: 这些都是悲观的例子吗?还是这样写代码有益?

Example 1: 范例1:

int findVal(const int OTHER_VAL) const
{
    switch(OTHER_VAL)
    {
    case 1:
        return 2;
    default:
        return 3;
    }
}

Example 2: 范例2:

enum class MobType
{
    COW, CHICKEN, DOG, PIG
};

class BaseMob
{
protected:
    BaseMob(const MobType TYPE) : TYPE(TYPE) { }

    const MobType TYPE;
};

Example 3: 范例3:

void showWorld(const World &world)
{
    auto data = world.getData();
    for (auto &i:data)
        i.print();
}

No, they aren't. 不,不是。

const on local variables with automatic storage (including function args) is purely syntactic sugar to help human programmers set rules for their code. 具有自动存储功能的局部变量(包括函数args)上的const纯粹是语法糖,可帮助人类程序员为其代码设置规则。 It doesn't help the optimizer at all. 它根本没有帮助优化器。 Optimizing compilers extract the necessary data-movement from the C source, and optimize that. 优化的编译器从C源代码中提取必要的数据移动,然后对其进行优化。 They generally don't care if you reuse the same tmp variable for many different things, or have 10 different const tmp1 = a+10; 他们通常不在乎您是否将同一个tmp变量用于许多不同的事情,或者有10个不同的const tmp1 = a+10; in the same function. 在相同的功能。

And yes, this applies to function args passed by value; 是的,这适用于按值传递的函数args。 they are local variables with automatic storage, passed in registers or on the stack. 它们是具有自动存储的局部变量,可以传入寄存器或在堆栈中传递。 And no, this doesn't mean the caller can assume that a function didn't modify the stack memory used for arg-passing, so it doesn't help the optimizer much either. 不,这并不意味着调用者可以认为函数没有修改用于arg传递的堆栈内存,因此也对优化器没有太大帮助 (Making a 2nd function call with the same arguments still requires re-writing the args to the stack (if not all args fit in registers), because the const on an arg doesn't change the fact that the called function "owns" that stack space and can use it as scratch space however it wants.) (使用相同参数进行第二次函数调用仍需要将args重新写入堆栈(如果并非所有args都适合寄存器),因为arg上的const不会改变被调用函数“拥有”以下事实的事实:堆栈空间,并可以根据需要将其用作临时空间。)


const on static/global/reference variables does help. const静态/全局/引用变量确实有帮助。 static const int foo = 10; can be inlined as an immediate constant instead of loaded from memory. 可以作为立即常量内联而不是从内存中加载。 (eg add eax, 10 instead of add eax, [foo] ). (例如, add eax, 10而不是add eax, 10而不add eax, [foo] )。


Using const to mark a class method as not changing any class members can also help the compiler avoid re-loading class members after a function call. 使用const将类方法标记为不更改任何类成员也可以帮助编译器避免在函数调用后重新加载类成员。 (ie keep them live in registers). (即将它们保留在寄存器中)。 This mostly only applies if the compiler can't see the function definition, otherwise a good optimizing compiler can just look at what the called function does and optimize accordingly. 这仅在编译器看不到函数定义的情况下才适用,否则,一个好的优化编译器可以仅查看被调用函数的功能并相应地进行优化。 (As long as it's not in a Unix library, where symbol interposition means that it can't assume the called function it sees at compile time will be the one called after dynamic linking.) (只要它不在Unix库中,其中的符号插入意味着它不能假定它在编译时看到的被调用函数将是动态链接之后被调用的函数。)

Whenever you logically do not alter a value or an object you should make it const . 只要逻辑上不更改值或对象,就应将其设置为const By logically I do not mean every time you are technically allowed to, but every time it is logical in the context of your functions, classes and code. 从逻辑上讲,我并不是指每次在技术上都允许您这样做,而是每次在您的函数,类和代码的上下文中都是合乎逻辑的。

A simple example could be a simple "get" function as seen in example 1, these functions should not modify the state of the class, and should therefore be marked constant, as this will help document your intent to the user, besides helping you ensure the invariance of the class. 一个简单的示例可以是示例1中所示的简单“ get”函数,这些函数不应修改类的状态,因此应将其标记为常量,因为这将有助于向用户说明您的意图,同时还可以帮助您确保类的不变性。

There are situations where it makes sense to make an immutable object, as seen in example 2. It is not that often we see these in C++, but many other languages use them frequently. 如例2所示,在某些情况下,使不可变的对象有意义。在C ++中我们并不经常看到它们,但是许多其他语言经常使用它们。 If it does not add any value to be able to change a certain member during an objects lifetime, you might as well make it const. 如果它没有添加任何值以能够在对象生存期内更改某个成员,则最好将其设置为const。

Passing const reference parameters gives you the performance benefits of the reference, but at the same time ensures that the source object is kept unmodified, which is both great documentation to the user, but also allows som optimizations to happen. 传递const引用参数可为您提供引用的性能优势,但同时可确保源对象保持不变,这对用户而言既是不错的文档,又可进行som优化。

Having mentioned all these reasons, there are other reasons to use const as briefly mentioned in the last paragraph, optimizations. 提到了所有这些原因之后,还有其他原因使用const如上一段优化中所述。 When the compiler knows that something is constant and is not being altered it can enable some pretty clever optimizations, don't use const for performance reasons though. 当编译器知道某些内容是恒定的并且没有被更改时,它可以启用一些非常聪明的优化,但是出于性能原因,请不要使用const

This is also why working around constness by (for instance) the const_cast cast, which can cast away const , can lead to some undesired behaviour. 这也是为什么通过(例如) const_cast (可以丢弃const会导致某些不良行为的原因。 As an example check out the following: 作为示例,请检查以下内容:

#include <stdio.h>

static const int foo = 10;

int constsum(void) {
  return foo + 5;
}

int main(int argc, char* argv[]) {
  int a = constsum();
  int* newFoo = const_cast<int*>(&foo);
  *newFoo = 20;
  int b = constsum();
  printf("%d\n", a + b);
  return 0;
}

As can be seen from this example ( see code running here ) this might not produce the desired result, as the code result in 30 being printed, and not as perhaps expected 40. 从该示例可以看出( 请参阅此处运行的代码 ),这可能不会产生期望的结果,因为该代码导致打印30 ,而不是预期的40。

When examining the produced assembly we can see why ( compiled into assembly ): 在检查生成的程序集时,我们可以看到原因( 编译为程序集 ):

constsum():
        mov     eax, 15
        ret
main:
        mov     eax, 30
        ret

The compiler simply inlines the values, as it can see that they constant, it does not take special care that the const_cast is being used. 编译器只是内联这些值,因为它们可以看到它们是常量,因此不必特别注意正在使用const_cast

So const correctness, and use of const is a valuable tool, that can benefit performance, and stability of your code, but also (and not to forget) it helps documenting your code. 因此const的正确性和const使用是一个有价值的工具,它可以提高代码的性能和稳定性,但同时(不要忘记)它有助于记录代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM