开发者

Is it ok to pass *this in the constructor in the following example

开发者 https://www.devze.com 2022-12-23 19:58 出处:网络
Class A { A(B& b) : mb(b) { // I will not access anything from B here } B& mb; }; Class B { B(): a(*this)
Class A
{
  A(B& b) : mb(b) 
   {
     // I will not access anything from B here
    }

  B& mb;
};


Class B
{
B(): a(*this)
{}

A a;
}

I run into such a situation may times, the contained object needs to use the containers functionality. Having a reference to the container object in the contained object seems to be the best way to do this. Of course, I could do this with a poin开发者_开发知识库ter, that way I could have a setter setB(B* b) {mb = b;} which I could call later after I am sure B is initialized but I would much prefer to do this with a reference which means I need to initialize it in the constructor, hence the problem.


Since you're only initializing the reference to B, this should be just fine -- by the time B's constructor runs the memory location for it has already been setup.

Do keep in mind that you can't call any methods in B safely from A's constructor because B has not finished constructing yet.


The appropriate quote from the standard is:

§3.8 [basic.life]/6

Similarly, before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any lvalue which refers to the original object may be used but only in limited ways. Such an lvalue refers to allocated storage (3.7.3.2), and using the properties of the lvalue which do not depend on its value is well-defined. If an lvalue-to-rvalue conversion (4.1) is applied to such an lvalue, the program has undefined behavior; if the original object will be or was of a non-POD class type, the program has undefined behavior if:

— the lvalue is used to access a non-static data member or call a non-static member function of the object, or 
— the lvalue is implicitly converted (4.10) to a reference to a base class type, or 
— the lvalue is used as the operand of a static_cast(5.2.9) (except when the conversion is ultimately to char& or unsigned char&), or 
— the lvalue is used as the operand of a dynamic_cast(5.2.7) or as the operand oftypeid.


It depends what you are doing in the A constructor.

The B object is not fully constructed until the constructor returns. Furthermore, before you enter the body of the B constructor, the objects within the B object may not be fully constructed. For example:

class B
{
    A a;
    std::string str;

public:
    B() : a(*this)
    {
    }
};

At the time that A::A is called, str is not yet constructed. If you try to use str within A::A (either directly or indirectly), you will have undefined behavior.

0

精彩评论

暂无评论...
验证码 换一张
取 消