C++ 在声明变量后是否有一些忍者技巧可以使变量保持不变?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3669315/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 13:25:44  来源:igfitidea点击:

Is there some ninja trick to make a variable constant after its declaration?

c++c++11const-correctness

提问by Thomas Bonini

I know the answer is 99.99% no, but I figured it was worth a try, you never know.

我知道答案是 99.99% 不,但我认为值得一试,你永远不知道。

void SomeFunction(int a)
{
    // Here some processing happens on a, for example:
    a *= 50;
    a %= 10;
    if(example())
       a = 0;
    // From this point on I want to make "a" const; I don't want to allow
    // any code past this comment to modify it in any way.
}

I can do something somewhat similar with const int b = a;, but it's not really the same and it creates a lot of confusion. A C++0x-only solution is acceptable.

我可以用 做一些类似的事情const int b = a;,但它并不完全相同,并且会造成很多混乱。仅 C++0x 的解决方案是可以接受的。

EDIT: another less abstracted example, the one that made me ask this question:

编辑:另一个不太抽象的例子,那个让我问这个问题的例子:

void OpenFile(string path)
{
    boost::to_lower(path);
    // I want path to be constant now
    ifstream ...
}

EDIT: another concrete example: Recapture const-ness on variables in a parallel section.

编辑:另一个具体的例子:Recapture const-ness on variables in a parallel section

采纳答案by JaredPar

One solution would be to factor all of the mutation code into a lambda expression. Do all of the mutation in the lambda expression and assign the result out to a const intin the method scope. For example

一种解决方案是将所有变异代码分解为一个 lambda 表达式。执行 lambda 表达式中的所有更改const int,并将结果分配给方法范围内的 a。例如

void SomeFunction(const int p1) { 
  auto calcA = [&]() {
    int a = p1;
    a *= 50;
    a %= 10;
    if(example())
       a = 0;
    ..
    return a;
  };
  const int a = calcA();
  ...
}

回答by bdonlan

You could move the code to generate ainto another function:

您可以将要生成的代码移动a到另一个函数中:

int ComputeA(int a) {
  a *= 50;
  a %= 10;
  if (example())
    a = 0;
  return a;
}

void SomeFunction(const int a_in) {
  const int a = ComputeA(a_in);
  // ....
}

Otherwise, there's no nice way to do this at compile time.

否则,在编译时没有好的方法可以做到这一点。

回答by mb14

A pattern I used to use is to "hide" the argument with an _, so the code becomes

我曾经使用的一种模式是用_“隐藏”参数,因此代码变为

void SomeFunction(int _a)
{
    // Here some processing happens on a, for example:
    _a *= 50;
    _a %= 10;
    if(example())
       _a = 0;

    const int a = _a;
    // From this point on I want to make "a" const; I don't want to allow
    // any code past this comment to modify it in any way.
}

You could also use only const variables and make a function to compute the new value of a, if necessary. I tend more en more to not "reuse" variables en make as much as possible my variables immutable : if you change the value of something , then give it a new name.

如有必要,您也可以仅使用 const 变量并创建一个函数来计算 a 的新值。我更倾向于不“重用”变量使我的变量尽可能不可变:如果您更改某些内容的值,则给它一个新名称。

void SomeFunction(const int _a)
{
    const int a = preprocess(_a);
    ....

}

回答by dirkgently

Why not refactor your code in to two separate functions. One that returns a modified aand another that works on this value (without ever changing it).

为什么不将您的代码重构为两个单独的函数。一个返回一个修改过的a,另一个处理这个值(不改变它)。

You could possibly wrap your object too around a holder class object and work with this holder.

您也可以将您的对象包裹在一个持有者类对象周围并与这个持有者一起工作。

template <class T>
struct Constify {
    Constify(T val) : v_( val ) {}
    const T& get() const  { return v_; }
};

void SomeFuncion() {
    Constify ci( Compute() ); // Compute returns `a`
    // process with ci
}

Your example has an easy fix: Refactoring.

您的示例有一个简单的解决方法:重构。

// expect a lowercase path or use a case insensitive comparator for basic_string
void OpenFile(string const& path)  
{        
    // I want path to be constant now
    ifstream ...
}

OpenFile( boost::to_lower(path) ); // temporaries can bind to const&

回答by Mark B

I don't actually suggest doing this, but you could use creative variable shadowing to simulate something like what you want:

我实际上并不建议这样做,但您可以使用创意变量阴影来模拟您想要的东西:

void SomeFunction(int a)
{
    // Here some processing happens on a, for example:
    a *= 50;
    a %= 10;
    if(example())
       a = 0;
    {
        const int b = a;
        const int a = b;  // New a, shadows the outside one.
        // Do whatever you want inside these nested braces, "a" is now const.
    }
}

回答by alvin

this might be one way to do it, if you are just trying to avoid another name. i suggest you think twice before using this.

如果您只是想避免使用其他名称,这可能是一种方法。我建议你在使用之前三思而后行。

int func ()
{
    int a;
    a %= 10;

const int const_a = a;
#define a const_a

    a = 10;  // this will cause an error, as needed.
#undef a
}

回答by Jeremy Trifilo

Answers were pretty solid, but honestly I can't really think of a GOOD situation to use this in. However in the event you want to Pre-Calculate a constant which is basically what you are doing you have a few main ways You can do this.

答案非常可靠,但老实说,我真的想不出使用它的好情况。但是,如果您想预先计算一个常数,这基本上就是您正在做的事情,您有几种主要方法可以做这个。

First we can do the following. So the compiler will simply set CompileA# for us in this case it's 50, 100, and 150.

首先,我们可以执行以下操作。因此,在这种情况下,编译器将简单地为我们设置 CompileA# 为 50、100 和 150。

const int CompileA1 = EarlyCalc(1);
const int CompileA2 = EarlyCalc(2);
const int CompileA3 = EarlyCalc(3);

int EarlyCalc(int a)
{
    a *= 50;
    return a;
}

Now anything beyond that there's so many ways you can handle this. I liked the suggestion as someone else had mentioned of doing.

现在,除此之外的任何事情都有很多方法可以处理。我喜欢这个建议,就像其他人提到的那样。

void SomeFunc(int a)
{
    const int A = EarlyCalc(a);
    //We Can't edit A.
}

But another way could be...

但另一种方式可能是......

SomeFunc(EarlcCalc(a));

void SomeFunc(const int A)
{
    //We can't edit A.
}

Or even..

甚至..

SomeFunction(int a)
{
    a *= 50;
    ActualFunction(a);
}

void ActualFunction(const int A)
{
    //We can't edit A.
}

回答by Oleg

Sure, there is no way to do it using the same variable name in C++.

当然,没有办法在 C++ 中使用相同的变量名来做到这一点。