最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

constructor - Lazy initialization of const attributes in c++ - Stack Overflow

programmeradmin6浏览0评论

I would like to carry out a lazy initialization of a set of (std::vector) attributes in c++. They have to be const, in the sense that after the first time they are initialized (via a get method), their values cannot be modified. What is the cleanest way to do this?

I tried to define the attributes as const, but in this way they must be initialized in the construntor initialization list, so no lay initialization seems to be possible.

I would like to carry out a lazy initialization of a set of (std::vector) attributes in c++. They have to be const, in the sense that after the first time they are initialized (via a get method), their values cannot be modified. What is the cleanest way to do this?

I tried to define the attributes as const, but in this way they must be initialized in the construntor initialization list, so no lay initialization seems to be possible.

Share Improve this question asked Jan 18 at 14:50 AntonioAntonio 232 bronze badges 3
  • Via a constexpr std::vector + immediately invoked (constexpr) lambda. Assuming you know /can calcluate everything at compile time. Otherwise you can use a "meyer's singleton approach" const std::vector<int>& getConstVector() { static std::vector<int> values = immediate_invoked_lambda[]{ ... initialization code here ... }(); return values; } – Pepijn Kramer Commented Jan 18 at 15:03
  • 1 You don't want const, you want logically constant. Then implement a lazy<T> for your lazily initialized set of attributes. Make the lazy<T> have a logically constant interface, rather than be a const object itself. – Eljay Commented Jan 18 at 15:10
  • While a const vector cannot be modified in size it's contents can be since they cannot be const. see this – doug Commented Jan 18 at 16:28
Add a comment  | 

3 Answers 3

Reset to default 3

You might do something like:

class MyClass
{
public:
    const std::vector<int>& getV()
    {
        if (!v) {
            v = std::vector{4, 8, 15, 16, 23, 42};
        }
        return *v;
    }
private:
    std::optional<std::vector<int>> v;
};

If some specific value is "prohibited" from vector (as empty vector), you might remove optional and use that value instead.

You may use the "Meyer's singleton" pattern by using a static in the getter itself. This give the guaranty to be initialized on first access (and is even thread safe)

struct MyClass
{
    const std::vector<int>& getV()
    {
       static auto v = std::vector{4, 8, 15, 16, 23, 42};
    
       return v;
    }
};

full working example there => https://godbolt./z/8jheTq1WT

Proper handling of Lazy initialization needs language support that is currently unavailable in C++. But using the return value of functions is a possibility. Therefore, we can use the IILE(immediately invoked lambda expression) pattern:

auto const my_lazy_vec = 
[& /*capture all by ref*/ ]{
    std::vector<elements> nrvo;
    {// safety scope for nrvo
        if (case_1)
           do_fill(nrvo, value_set_1);
        else if (case_2)
           do_fill(nrvo, value_set_2);
        else if (case_3)
           do_fill(nrvo, value_set_3);
        return nrvo;
    };//safety scope for nrvo
}(/*IILE*/);// init my_lazy_vec

In the above snippet nrvo is not essential, but serves as a good example. Using lambda, makes the initialization logic local and visible - while still conditional and flexible. And the result of immediate evaluation is directly initialized into a const object. In other words, the mutable stage of object's lifetime is handled inside the lambda, while the immutable part is handled by the return value.

发布评论

评论列表(0)

  1. 暂无评论