-1

Ok, let try to write a piece of code more similar to my real case, please take it as an example, it does not have to compile:

class A
{
    public:

    A() = delete;
    A(int value);
    ...
}

class B
{
    unique_ptr<A> a;
    C c;

    B() { a = make_unique<A>(c.getValue()); }
}

class C
{
    public:

    C();
    int getValue() { return <an int value based on something>; }
}

Now I hope my question is clearer, because of some constraints I cannot pass int value to B constructor, then I cannot use initializer list. So, is my unique_ptr solution the preferred one? Thanks again.

Pampo
  • 19
  • 3
  • 1
    Your better C++ solution doesn't compile because `args` is undeclared. – john Jul 29 '20 at 09:23
  • This seems to be the inherent problem in your B class. You want to construct it when you do not have all the information necessary to fully construct it. If you can't fix that for some reason then what wrong with the `init(args)` solution? It's not ideal but only because your class design is not ideal. – john Jul 29 '20 at 09:24
  • 2
    In addition to `std::unique_ptr` also consider `std::optional`, which places `T` inside itself, not on heap. – Evg Jul 29 '20 at 09:27
  • 4
    If `B` knows the `args` (as suggested in pointer variants), then you are looking for [member initializer list](https://en.cppreference.com/w/cpp/language/constructor). No pointers or optionals needed. – Yksisarvinen Jul 29 '20 at 09:28
  • You could keep your original definition of `B` and pass the required (or dummy) argument to the `A` constructor in the `B` initializer list: `B() : a{ dummyargs } {}`. – Adrian Mole Jul 29 '20 at 09:29
  • 8
    I second Yksisarvinen. It looks to me like your entire dilemma is based around the habit of using assignment in your c'tor bodies, instead of initialization. It's [a habit worth breaking](https://stackoverflow.com/questions/926752/why-should-i-prefer-to-use-member-initialization-lists). – StoryTeller - Unslander Monica Jul 29 '20 at 09:30
  • 1
    Please edit to provide more details about your specific use case. It is currently vague and unclear, why you think you need to have a default constructor and 'initialise' later. – underscore_d Jul 29 '20 at 09:51
  • You have two answers - if they didn't help enough, why not ask a supplementaty question under the answers you've gotten? Did you abandon this question? If so, delete it. – Ted Lyngmo Aug 08 '20 at 01:06

2 Answers2

2

The smart pointer version is if course better than the bare one, but I'm unconvinced that dynamic allocation or pointer would be needed in the first place. I suggest simply to not default initialise A:

struct A
{
    A() = delete;
    A(args);
};

struct B
{
    A a {args{}};
};
eerorika
  • 232,697
  • 12
  • 197
  • 326
1

There is nothing stopping you from doing

class A
{
    A() = delete;
public:
    A(Args);
    // more members...
}

class B
{
    A a;

public:
    // if B has sensible defaults for args
    B() : a(default_args /*some default args*/) {} 
    // otherwise
    B(Args args) : a(args) {}
}
Caleth
  • 52,200
  • 2
  • 44
  • 75