为了账号安全,请及时绑定邮箱和手机立即绑定

是否可以像 Java 的“空白最终”功能那样,在C++中推迟 const 变量的初始化?

是否可以像 Java 的“空白最终”功能那样,在C++中推迟 const 变量的初始化?

拉风的咖菲猫 2022-09-14 15:56:15
在Java中,我们可以声明一个空白的最终变量,并在以后对其进行初始化。编译器将确保初始化只发生一次 - 初始化失败或双重初始化都是编译时错误。例如:public int bar() {   return 66;}public void foo() {    final int x; // declare the variable    ...    x = bar(); // initialization only once}在Java中,编译器可以保证在第一次赋值之前绝对不会在任何代码路径上赋值,并且可以保证它绝对不会在任何代码路径上被分配第二次。(有关更多信息,请参见 Java 语言规范的第 16 章 “确定赋值”。x我们如何在C++中实现类似的行为?是否可以声明变量但推迟其初始化?(不丢弃说明符。constconst
查看完整描述

2 回答

?
白板的微信

TA贡献1883条经验 获得超3个赞

除非定义了 const,否则无法对其进行初始化。你必须找到一种方法来知道它的定义价值。如果 很难确定 的值,请考虑使用函数的结果,例如x

const int x = calc_x();

或类似的闭包

const int x = []() { /* code to calculate x's value */ }();

constness 是对象类型的一部分,并且对象类型在任何情况下都不能更改,因此要么是,您以后无法初始化它,要么根本不是。xconstxconst

可以设计一个可以模拟此内容的包装器,但您最多只能得到一个运行时错误。class

请注意,似乎可能存在以下形式的解决方案,但假设所讨论的对象实际上不是 。在初始化后无法合法更改其值的情况下。const_castconstconst int x


查看完整回答
反对 回复 2022-09-14
?
慕斯王

TA贡献1864条经验 获得超2个赞

C++没有内置功能。不过,您可以自己构建它。您可以创建一个类来保存所需类型的对象的存储空间,并且可以重载该对象的赋值运算符,以便只能调用和初始化一次。这看起来像


template<typename T>

class once

{

private: 

    std::aligned_storage_t<sizeof(T), alignof(T)> data;

    T* ptr = nullptr;

public:

    once() = default;

    ~once()

    {

        if(ptr) // it is initialized so call the destructor

            ptr->~T();

        // optionally you can add

        // throw("a once<T> must be initialized once");

        // this can help to enforce that the object is actually initialized as you'll get a runtime exception in code that does not do so

    }

    template<typename U>

    once& operator =(U&& value)

    {

        if (!ptr) // it is not initialized so call constructor

        {

            ptr = new(&data) T(std::forward<U>(value));

        }

        else

            throw ("can only assign to a once<T> once.");

        return *this;

    }

    operator const T&()

    {

        return *ptr;

    }


};

然后你会像这样使用它


int main()

{

    once<int> foo;

    if (1 < -1)

        foo = 21;

    else

        foo = 42;

    std::cout << foo;

    //foo = 23; // uncomment this to get an exception.

}


查看完整回答
反对 回复 2022-09-14
  • 2 回答
  • 0 关注
  • 70 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信