3

I'm having a memory violation error and I don't know where it comes from. My question is : am I allowed to get the address of a class member while inside the constructor initialization list so that I can pass it to an object that needs a reference to it ?

For example :

class A
{
};

class ReferencesA
{
    A * const pA;

    ReferencesA( A * ptrA ) : pA( ptrA ) { }
};

class B
{
    A a;

    ReferencesA referencesA;

    B() : referencesA( & a ) { }
};

Is is safe to & a inside the constructor initialization list ? It seems to me that it would be, but things don't always work like we expect.

Thank you.

1
  • Looks ok to me. It could be what "referencesA" does with the ptrA inside its ctor that is causing the crash, Especially if "a" has not been constructed yet. Commented Nov 3, 2015 at 15:57

1 Answer 1

2

The order of the initialisation of the base members in class B is a, then referencesA. That's because they appear in that order in the class declaration. (The order in which they appear, if at all, in the initialisation list in your constructor is not relevant.)

So using &a to initialise referencesA is safe, if a little brittle. In your case, &a is the address of the default-constructed member a.

I'd advise against coding like this in case someone changes the order of the members in your class.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks. The problem is that, if i want to have const pointers (or references) to indicate that the pointer will be the same and valid for the whole lifetime of the object, then i need to initialize things in the initializer list, else i can't use const.
It's worth noting that saving a pointer to an uninitialized object is safe, so the order in the class doesn't matter. a only has to be first in the class list if you want to read or write through the pointer.
@MooingDuck do you have a reference for that?
@haelix: I don't, but it's so common that you'd have to think about it to even realize that's what we've all been doing. char buffer[30]; memset(buffer, 0, 30); No one would argue that it's undefined behavior to pass the pointer to uninitialized memory to memset. When you call a member method from a constructor, that also does it, because it passes an implicit this pointer to the method but the derived constructors haven't been called yet. Heck even int x; std::cin >> x; passes a reference to uninitialized memory.
@MooingDuck Ah ok I meant specifically constructing members using addresses/references of members coming later in declaration order. I looked for a reference and couldn't find anything (class.base.init). I can only think it's OK given this is accessible and offsets should have been computed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.