1

Win7-64 bits cygwin g++ -std=gnu++11 (4.8.3)

In the fragment below the variable 'partition' must be initialized after the call to slipInit. The compiler complains (oh so bitterly) unless I initialize partition in the definition (after the ':'). I've just started using gnu++11 and so this is an unfortunate surprise. Are there any easy workarounds or must I create another method to do the initialization?

StringPartition::StringPartition(vector<string*>* vec, long debugFlags) 
                                : vec(*vec)
                            , debugFlags(debugFlags) {
      SlipCellBase::slipInit(SLIPALLOCATION, SLIPALLOCATION);
      partition = * new SlipHeader();
}; // StringPartition::StringPartition()

Error Message
error: uninitialized reference member 'StringPartition::partition' [-fpermissive]
lostbits
  • 782
  • 6
  • 20
  • 2
    Seems as though `partition` would probably better as a smart pointer than a reference. – Fred Larson Nov 05 '14 at 15:06
  • What is and how do I construct a 'smart pointer' (I'm only a dumb programmer)? – lostbits Nov 05 '14 at 15:13
  • Read this: http://stackoverflow.com/q/106508/10077 C++11 provides several smart pointer types. The most popular are [`std::unique_ptr`](http://en.cppreference.com/w/cpp/memory/unique_ptr) and [`std::shared_ptr`](http://en.cppreference.com/w/cpp/memory/shared_ptr). – Fred Larson Nov 05 '14 at 15:14
  • 1
    *Why* is `partition` a reference? Those are meant to refer to things that already exist, not newly created things. – molbdnilo Nov 05 '14 at 15:34

2 Answers2

2

Since you're trying to initialize a reference data member (since C++11 you can either do that in the constructor's initializer list or with a brace-or-equal initializer) but it requires a function call first, you should prefer a smart pointer over a reference (pseudocode ahead):

class StringPartition {
  public:

  StringPartition() {
      SlipCellBase::slipInit(SLIPALLOCATION, SLIPALLOCATION);
      partition.reset(new SlipHeader());
  }

  std::unique_ptr<SlipHeader> partition;
};

In C++14 you could even do better:

partition = std::make_unique<SlipHeader>();
Marco A.
  • 41,192
  • 25
  • 117
  • 233
0

You can't "initialise" members in the constructor body. You may only assign to them. All members are assuredly initialised — with their default constructors, and only if it's possible (else compilation failure) — before execution of the constructor body commences. Since partition is a reference, it must be initialised and cannot be default-initialised.

Your problem has arisen because SlipCellBase does not take advantage of RAII and therefore does not fit into the 21st century model of resource management within classes. Your best option is probably to make partition a std::unique_ptr<SlipHeader> so that it can take on an "unset" value until you're ready to assign to it. The smart nature of std::unique_ptr<> will clean it up for you when your StringPartition goes out of scope. Still, be under no illusion: this is still, ultimately, a hack around poor design.

Lightness Races in Orbit
  • 358,771
  • 68
  • 593
  • 989