C ++ constructor: initialize a local variable before the list of initializers

How to save the temporary state necessary for the list of initializers in the constructor (on the stack)?

For example, the implementation of this constructor ...

// configabstraction.h
#include <istream>

class ConfigAbstraction
{
public:
    ConfigAbstraction(std::istream& input);

private:
    int m_x;
    int m_y;
    int m_z;
};

... using a helper class like this?

// mysillyparserdontworry.h
#include <json/reader.h> //jsoncpp

class MySillyParserDontWorry
{
public:
    MySillyParserDontWorry(std::istream& input) { input >> m_parseTree; }
    int intByName(const char* name) const { return m_parseTree[name].asInt(); }

private:
    Json::Value m_parseTree;
};

My attempt:

// configabstraction.cpp

ConfigAbstraction::ConfigAbstraction(std::istream& input)
    : local_parserState(input) // init local variable first: Not possible!
    , m_a(local_parserState.intByName("a"))
    , m_b(local_parserState.intByName("b"))
    , m_c(local_parserState.intByName("c"))
{
    MySillyParserDontWorry local_parserState; // ...because it is local
}

What an artificial limitation of C ++!

+4
source share
4 answers

With C ++ 11, you can solve this by delegating constructors:

class ConfigAbstraction
{
public:
    ConfigAbstraction(std::istream& input);

private:
    ConfigAbstraction(const MySillyParserDontWorry& parser);

    int m_a;
    int m_b;
    int m_c;
};

ConfigAbstraction::ConfigAbstraction(const MySillyParserDontWorry& parser)
    : m_a{parser.intByName("a")}
    , m_b{parser.intByName("b")}
    , m_c{parser.intByName("c")}
{
}

ConfigAbstraction::ConfigAbstraction(std::istream& input)
    : ConfigAbstraction{MySillyParserDontWorry{input}}
{
}
+5
source

Why not just make assignments in the constructor body, then?

ConfigAbstraction::ConfigAbstraction(std::istream& input)
    : m_a(0)
    , m_b(0)
    , m_c(0)
{
    MySillyParserDontWorry local_parserState;
    m_a = local_parserState.intByName("a");
    m_b = local_parserState.intByName("b");
    m_c = local_parserState.intByName("c");
}

Is there any specific requirement that prevents you from doing this?


What an artificial limitation of C ++!

. ? , ( ).

+1

int . . const ( ).

std::tuple. struct std::array<int, 3>; : - .

#include <istream>
#include <tuple>

class MySillyParserDontWorry
{
public:
    MySillyParserDontWorry(std::istream& input) { /* ... */  }
    int intByName(const char* name) const { return /* ... */ 0; }

};

class ConfigAbstraction
{
public:
    ConfigAbstraction(std::istream& input);

private:

    static std::tuple<int, int, int> parse(std::istream& input)
    {
        std::tuple<int, int, int> result;
        MySillyParserDontWorry parser(input);
        std::get<0>(result) = parser.intByName("a");
        std::get<1>(result) = parser.intByName("b");
        std::get<2>(result) = parser.intByName("c");
        return result;
    }

    std::tuple<int, int, int> const m;
};


ConfigAbstraction::ConfigAbstraction(std::istream& input)
    : m(parse(input))
{
}
0

You cannot initialize local variables to members. The reason for this is very simple (so this is NOT an artificial limitation):

Members must be initialized (constructed) before the start of the constructor body, because the constructor body can access them - and they must be initialized for this access. On the other hand, local variables do not exist before the code enters the body of the constructor (as for any other function). Conclusion - initialization of local variables before members is not possible.

0
source

Source: https://habr.com/ru/post/1614183/


All Articles