代码之家  ›  专栏  ›  技术社区  ›  Andreas Bonini

有什么忍者的把戏让一个变量在声明后变为常量吗?

  •  45
  • Andreas Bonini  · 技术社区  · 15 年前

    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 回复  |  直到 9 年前
        1
  •  48
  •   Johan    5 年前

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

    甚至

    void SomeFunction(const int p1) { 
      const int a = [&]() {
        int a = p1;
        a *= 50;
        a %= 10;
        if(example())
           a = 0;
        ..
        return a;
      }();
      ...
    }
    
        2
  •  47
  •   bdonlan    15 年前

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

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

        3
  •  11
  •   mb14    15 年前

    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);
        ....
    
    }
    
        4
  •  10
  •   dirkgently    15 年前

    为什么不把代码重构成两个独立的函数呢。返回修改后的 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&
    
        5
  •  6
  •   Mark B    15 年前

    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
  •  5
  •   alvin    15 年前

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

    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
    }
    
        7
  •  0
  •   Jeremy Trifilo    7 年前

    答案是相当可靠的,但老实说,我真的想不出一个好的情况下使用这个。然而,如果你想预先计算一个常数,这基本上就是你正在做的,你有几个主要的方法可以做到这一点。

    首先,我们可以做以下工作。因此编译器只需为我们设置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.
    }
    
        8
  •  -1
  •   Oleg    15 年前

    当然,在C++中没有使用相同变量名的方法。