idanshmu
idanshmu

Reputation: 5271

Complex initialization for a const variable while avoiding new allocation

I'm trying to initialize const& variable. The value of a the variable I'm trying to initialize depends on some condition.
For example:

typedef std::vector<string> string_vector;
string_vector data_pool;

const string& data;
if( some_cond )
  {
    // do something and set data
    data = data_pool[some_index1]
  }
 else
   {
     // do something and set data
    data = data_pool[some_index2]
   }

Of course the code above is not valid, but this is what I'm trying to do.

I can use ternary operator:

const string& data = (some_cond)? data_pool[some_index1] : data_pool[some_index2];

but this syntax doesn't really let me do anything other than to set the value.

So now I try to use lambda expression (not too sure I got it right):

const string& data = [&]{

    string tmp = "";  
      {
        // do something and set tmp
        tmp = data_pool[some_index1]
      }
    else
      {
        // do something and set tmp
        tmp = data_pool[some_index2]
      }

    return tmp;
}

but my problem here is that this solution requires new string allocation which I cannot afford at this point since this piece of code is the bottle neck of my program.

Question
How can data be initialize in a complex manner but efficiently?

Note
I can workaround the problem quite easily. data will eventually refer to some item in data_pool so all I need to do is to calculate the desired index and then initialize data. However I'm not interested in the workaround but rather in an elegant technique/practice for this elementary issue. what if the initialization is a bit more complex than calculating some index in a vector.

Upvotes: 1

Views: 1198

Answers (1)

JBL
JBL

Reputation: 12907

You can do that using a function or a lambda. Both solution can be done so that no allocation is performed and the const reference actually alias the data present in data_pool.

With a function, that'd be:

const std::string& initConstString(string_vector& pool){
    std::size_t index;

    //complex initialization stuff

    return pool[index];
}

With a lambda:

auto lambda = [&data_pool]() -> const std::string&{
    std::size_t index = 0;//For the sake of example
    //perform initialization here
    return data_pool[index];
};

const std::string& constString = lambda();

Live example for the lambda version on Coliru

I'd personally prefer the function if the initialization represents lot (well, > 4-5 lines) as I like my lambdas to be short and concise, but that's up to you.

Upvotes: 3

Related Questions