0

Just by curiosity, is it possible to declare a reference to an inner class in an outer class :

class A{
    private:
        class B{
            public:
                B(double val):val_(val){}
            private:
                double val_;
        };

    public:
        A(double val):b(B(val)){} /*problem*/

    private:
        B& b;
};

int main(){
    A a(1.0);
}

It feels logic that it is impossible because I don't see how one can assign a reference to a temporary variable. But I'd like to be sure. (I would like to use a ref rather than a pointer to guarantee the presence of a B in A.)

Edit

As I had the question why I'd like to do that, here is my goal. Let's imagine that the class B contains a lot of data and require a lot of memory. I don't want to have many copy of B otherwise I will run out of memory. Now I have two class C and D that both inherit of A. I want them to be related to the same instance of B. I could do that with a pointer, but as said before I want to make sure that at least a B exists somewhere, so I though that by using a ref I would be able to guarentee that. I also would like B to be an inner class so that I don't pollute my code. Thanks to your help, I now use a rvalue reference and my code looks like this :

class A{
    class B{
        public:
            B(double val):val_(val){}
        private:
            double val_;
    };

    public:
    A(double val):b(B(val)){}
    A(A const& a):b(a.b){}/*new problem*/

    protected:
    B&& b;
};

class C: public A{
    public:
        C(A const& a):A(a){}
};

class D: public A{
    public:
        D(A const& a):A(a){}
};

int main(){
    A a(1.0);
    C c(a);
    D d(a);
}

but it doesn't compile.

PinkFloyd
  • 2,103
  • 4
  • 28
  • 47
  • You seem to have mangled two questions together and come out with a non-question. What are you actually asking? – juanchopanza Jun 02 '15 at 15:25
  • 1
    @juanchopanza I haven't mangled two questions... my sentence is parenthesis is just to explain why I ask my question... so I don't understand the downvote – PinkFloyd Jun 02 '15 at 15:31
  • Yes, you can do this. Keep in mind, however, that anytime you have a reference is a class member, it means the compiler can't synthesize an assignment operator for that type, and while you can define your own, it's often difficult to make it work as users will typically expect. – Jerry Coffin Jun 02 '15 at 15:33
  • @JerryCoffin, I'm not sure I understand your comment. Do you mean that I have do define my own `operator=` because if I don't the compiler won't do it efficiently ? I don't really care if it slows the code down when I `A` is instantiated (will be done only once) but I do care if each time I call for instance `b.do_something()` form a method in `A`. – PinkFloyd Jun 02 '15 at 15:39
  • @PinkFloyd: It means the compiler cannot do it _at all_, and therefore neither can you, unless you write your own `operator=` that deliberately ignores the reference. And why would you want that? There are exceptions to the rule but, in general, classes with reference members should be non-assignable. – Lightness Races in Orbit Jun 02 '15 at 15:41
  • @LightnessRacesinOrbit, I edited my question to answer why I'd like to do that – PinkFloyd Jun 02 '15 at 16:02
  • @PinkFloyd: That's not a reason. Having a real, proper, honest-to-god member of type `B` will guarantee the presence of the object far more than any pointer _or_ reference ever could, and it has the added bonus of being valid. :) – Lightness Races in Orbit Jun 02 '15 at 16:03
  • @LightnessRacesinOrbit, sure but each instance of A,C or D would have a new instance of B, which I can't afford – PinkFloyd Jun 02 '15 at 16:06
  • @PinkFloyd: Except that's what you're already trying to do, unless you mean to _share_ `B` instances. Your goal is not clear. – Lightness Races in Orbit Jun 02 '15 at 16:30
  • @LightnessRacesinOrbit I mean to share instances of B, this is why I'd like to have reference or pointer. sorry if my question was misleading – PinkFloyd Jun 02 '15 at 16:36
  • @PinkFloyd: If you want to share instances, then you should have `std::shared_ptr`s. – Lightness Races in Orbit Jun 02 '15 at 16:39

2 Answers2

3

No.

It'll compile if you use an rvalue reference:

class A
{
   struct B {};
   B&& b;

public:
   A() : b(B()) {}
};

int main()
{
    A a;
}

…but, annoyingly, this is a dangling reference by a special rule that prohibits the member b from extending the lifetime of that temporary B() as it otherwise might:

[C++11: 12.2/5]: [..] A temporary bound to a reference member in a constructor’s ctor-initializer (12.6.2) persists until the constructor exits. [..]

Now, if B were public, and if the B object were passed in from somewhere else, then you'd have achieved your goal:

struct A
{
   struct B {};
   B& b;

   A(B& b) : b(b) {}
};

int main()
{
    A::B b;
    A a(b);
}

(live demo)

But, failing that, I don't see what else you can do to achieve this.

It would seem to be of limited utility, though; just have an actual B member!

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • great, thanks... I really need to understand better this rvalue reference.... and this would allow me to avoid the use of `new` and `delete` if I had to use pointer. – PinkFloyd Jun 02 '15 at 15:32
  • I doubt your rvalue reference member expends the lifetime of the B() temporary. Might as well just have a value copy inside the class – KABoissonneault Jun 02 '15 at 15:37
  • @KABoissonneault: From where flows this "doubt"? – Lightness Races in Orbit Jun 02 '15 at 15:40
  • @PinkFloyd: Just have an actual `B` member, ideally. But, sure, you _can_ do this... – Lightness Races in Orbit Jun 02 '15 at 15:41
  • @LightnessRacesinOrbit Because const reference members don't expand the lifetime of temporaries according to the standard. I can't find anything mentioning that rvalue reference members work any differently. – KABoissonneault Jun 02 '15 at 15:51
  • @KABoissonneault: Don't they? Are you sure you're not thinking of [this subtly but crucially different scenario](http://stackoverflow.com/q/2784262/560648)? Notice how I am not passing a temporary into the constructor through a call, merely directly initialising the reference with one. – Lightness Races in Orbit Jun 02 '15 at 15:57
  • Oh, huh, I guess 12.2/5 says the same as you: _"A temporary bound to a reference member in a constructor’s ctor-initializer (12.6.2) persists until the constructor exits"_. – Lightness Races in Orbit Jun 02 '15 at 16:00
2

If you want an object to be shared between copied member, use a std::shared_ptr. It's the only standard way to guarantee your B object will persistently exist for all the A objects that use it.

KABoissonneault
  • 2,359
  • 18
  • 17