声明变量后,有一些忍者把变量设为常量吗?

我知道答案是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.
}

我可以使用const int b = a;做一些类似的操作,但是并不是完全一样,这会造成很多混乱。 可接受仅C ++ 0x的解决方案。

编辑:另一个不太抽象的示例,使我问这个问题:

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

编辑:另一个具体示例:在并行节中重新获取变量的一致性。

Thomas Bonini asked 2020-02-29T15:20:44Z
8个解决方案
46 votes

您可以将代码移动以将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);
  // ....
}

否则,没有很好的方法在编译时执行此操作。

bdonlan answered 2020-02-29T15:21:25Z
38 votes

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

void SomeFunction(const int p1) { 
  auto calcA = [&]() {
    int a = p1;
    a *= 50;
    a %= 10;
    if(example())
       a = 0;
    ..
    return a;
  };
  const int a = calcA();
  ...
}
JaredPar answered 2020-02-29T15:21:01Z
11 votes

我过去使用的模式是使用_来“隐藏”参数,因此代码变为

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.
}

您也可以仅使用const变量,并在需要时创建函数以计算a的新值。 我更倾向于不要“重用”变量,以使我的变量尽可能不变:如果更改某物的值,则给它起一个新的名字。

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

}
mb14 answered 2020-02-29T15:21:50Z
10 votes

为什么不将代码重构为两个单独的函数。 一个返回修改后的a,另一个返回此值(无需更改)。

您也可以将对象也包裹在一个holder类对象上,并使用该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
}

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

// 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&
dirkgently answered 2020-02-29T15:22:19Z
5 votes

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

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
}
alvin answered 2020-02-29T15:22:39Z
4 votes

我实际上不建议这样做,但是您可以使用创意变量阴影来模拟所需的内容:

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.
    }
}
Mark B answered 2020-02-29T15:22:59Z
0 votes

答案非常可靠,但是说实话,我真的想不起来要使用这种方法。但是,如果您要预先计算一个常量,这基本上就是您正在做的事情,那么您可以采用几种主要方法 这个。

首先,我们可以执行以下操作。 因此,在这种情况下,编译器只需为我们设置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;
}

现在,除此之外,还有许多方法可以处理此问题。 我喜欢别人提到的建议。

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

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

SomeFunc(EarlcCalc(a));

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

甚至..

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

void ActualFunction(const int A)
{
    //We can't edit A.
}
Jeremy Trifilo answered 2020-02-29T15:23:37Z
-1 votes

当然,在C ++中无法使用相同的变量名来实现。

Oleg answered 2020-02-29T15:23:57Z
translate from https://stackoverflow.com:/questions/3669315/is-there-some-ninja-trick-to-make-a-variable-constant-after-its-declaration