是否可以定义一个只能设置一次的变量?

时间:2016-03-04 16:07:17

标签: c++

我知道const,在创建之后无法更改。但我想知道是否有办法声明一个你只设置一次的变量,之后就不会覆盖。 在我的代码中,我希望避免使用bool变量,nFirst一旦设置为nIdx,就无法设置为{{1}的新值}}

我的代码:

nIdx

4 个答案:

答案 0 :(得分:13)

很容易推出自己的。

template<typename T>
class SetOnce
{
public:
    SetOnce(T init) : m_Val(init)
    {}

    SetOnce<T>& operator=(const T& other)
    {
        std::call_once(m_OnceFlag, [&]()
        {
            m_Val = other;
        });

        return *this;
    }

    const T& get() { return m_Val; }
private:
    T m_Val;
    std::once_flag m_OnceFlag;
};

然后只需使用变量的包装类。

SetOnce<int> nFirst(0);
nFirst= 1;
nFirst= 2;
nFirst= 3;

std::cout << nFirst.get() << std::endl;

输出:

  

1

答案 1 :(得分:11)

  

我想避免使用bool变量

您可以检查nFirst本身,因为它不会设置为负数。如:

int nFirst = -1;
int nIdx = 0;
BOOST_FOREACH(Foo* pFoo, aArray)
{
    if (pFoo != NULL)
    {
        pFoo->DoSmth();
        if (nFirst == -1)
        {
            nFirst = nIdx;
        }
    }
    nIdx++;
}

答案 2 :(得分:0)

你的问题是关于避免布尔,但也意味着需要保持稳定。

为了避免bool,我使用了boost :: optional,如下所示:

boost::optional<int> nFirst;
// .. 
if (!nFirst) nFirst = nIdx;
// and now you can use *nFirst to get its value

然后,您可以强制执行逻辑(而非文字)常量:

const boost::optional<int> nFirst;
// ..
if (!nFirst) const_cast<boost::optional<int>&>(nFirst) = nIdx;
// you can use *nFirst to get the value, any attempt to change it would cause a compile-time error

使用const_cast并不是最安全的做法,但在您的特定情况下,只要您只做一次就可以了。它简化了你的代码和你的意图:你确实想要一个const,它只是想要推迟它的初始化。

现在,正如songyuanyao建议的那样,你可以直接使用int而不是boost :: optional,但后者会使你的意图明确,所以我觉得这样做更好。在一天结束时,这是C ++,而songyuanyao的解决方案实际上是C风格的解决方案。

答案 3 :(得分:0)

cocarin's类似,但抛出异常而不是默默地忽略赋值:

template <typename T, typename Counter = unsigned char>
class SetOnce {
public:
    SetOnce(const T& initval = T(), const Counter& initcount = 1):
        val(initval), counter(initcount) {}
    SetOnce(const SetOnce&) = default;
    SetOnce<T, Counter>& operator=(const T& newval) {
        if (counter) {
            --counter;
            val = newval;
            return *this;
        }
        else throw "Some error";
    }
    operator const T&() const { return val; } // "getter"
protected:
    T val;
    Counter counter;
};

用法:

SetOnce<int> x = 42;
std::cout << x << '\n'; // => 42
x = 4;
// x = 5; // fails
std::cout << x << '\n'; // => 4

Online demo

相关问题