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

时间:2010-09-08 15:26:02

标签: c++ c++11 const-correctness

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

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

8 个答案:

答案 0 :(得分:46)

您可以将代码移动到另一个函数中生成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);
  // ....
}

否则,在编译时没有很好的方法。

答案 1 :(得分:38)

一种解决方案是将所有突变代码分解为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();
  ...
}

答案 2 :(得分:11)

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

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);
    ....

}

答案 3 :(得分:10)

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

您可以将对象包裹在持有者类对象周围并使用此持有者。

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&

答案 4 :(得分:5)

这可能是一种方法,如果你只是想避免使用其他名称。我建议你在使用它之前再三考虑。

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
}

答案 5 :(得分:4)

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

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

答案 6 :(得分:0)

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

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

答案 7 :(得分:-1)

当然,在C ++中使用相同的变量名是无法做到的。

相关问题