Thread: Constructor Question

  1. #1
    Registered User
    Join Date
    Aug 2003
    Posts
    21

    Constructor Question

    I should probably know this, but I don't so I'm hoping someone can fill me in.

    If I create an object using the default constructor, then pass that object via reference into a function whereon it gets a different constructor called on it for initialisation, is this a bad idea? What exactly happens?

    Something like this:

    Code:
    void MyFunc(MyObject& rInst)
    {
    	//Do some stuff.
    	
    	rInst = MyObject(PARAM_1, PARAM_2);
    	
    	//Do some more stuff.
    }
    
    int main(int argc, char **argv)
    {
    	MyObject objInst;
    	
    	MyFunc(objInst);
    	
    	return 0;
    }
    I know it's wrong to call one constructor from another...

    Code:
    class MyClass
    {
    	MyClass(int something)
    	{
    		MyClass();
    	}
    	
    	MyClass()
    	{
    		//Do some stuff.
    	}
    }
    ...because (according to the C++ FAQ) it just creates a local instance and immediately destroys it, rather than initialising the object. In which case, I would assume my first example to do the same.

    Can someone clear this up for me?

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Your example will call a (different) constructor, then use the assignment operator to copy that new object into your first object.

  3. #3
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    There's nothing wrong with this example, provided that the destructor and assignment operators are correct.

    However, in this case, it would probably be better for MyFunc() to NOT take the object by reference, but instead return a newly created object by value. That avoids the pointless default-construction followed by an assignment operation.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  4. #4
    Registered User
    Join Date
    Aug 2003
    Posts
    21
    The example I gave was a bad one in that the function I'm using already has a return value so I have to pass in either a reference or pointer.

    What I don't understand is how come it's valid to reinitialise an object via calling one of it's constructors yet it's not valid to extend the initialisation of an object by calling one of it's constructors from within another one.

    Also, what do you mean by "provided that the destructor and assignment operators are correct"? I haven't overridden any operators in my class so perhaps I'm missing something.

  5. #5
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> What I don't understand is how come it's valid to reinitialise an object via calling one of it's constructors yet it's not valid to extend the initialisation of an object by calling one of it's constructors from within another one. <<

    It's never valid to reinitialize an object by calling one of its constructors. What you are doing is assigning a new value to the object by calling the copy assignment operator. You first create a temporary MyObject using a regular MyObject constructor, then you assign the contents of that temporary object to the rInst instance.

    Theoretically, you could do the same (create a temporary and then assign it) inside a constructor, but that usually doesn't make as much sense as other initialization options.

    >> Also, what do you mean by "provided that the destructor and assignment operators are correct"? <<

    Sometimes class designers forget to make sure copying works properly. For example, if you have some resource in your class, like memory allocated with new, you have to write your own copy functions to make sure the resource is copied properly. Since in your code above the temporary is being copied into the rInst variable, that copy assignment operator must be correct for it to work properly.

  6. #6
    Registered User
    Join Date
    Aug 2003
    Posts
    21
    Quote Originally Posted by Daved View Post
    Theoretically, you could do the same (create a temporary and then assign it) inside a constructor, but that usually doesn't make as much sense as other initialization options.
    Not according to the C++ FAQ Lite. See here: "Instead it calls Foo::Foo(char,int) to initialize a temporary, local object (not this), then it immediately destructs that temporary when control flows over the ;. "

    Quote Originally Posted by Daved View Post
    you have to write your own copy functions to make sure the resource is copied properly.
    You mean write your own copy constructor to do a deep copy? I didn't write a copy constructor of my own (I don't think I need to as I haven't dynamically allocated any memory). For a shallow copy, you can just allow C++ to do it automatically like in my example, can't you?

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by redneon
    Not according to the C++ FAQ Lite. See here: "Instead it calls Foo::Foo(char,int) to initialize a temporary, local object (not this), then it immediately destructs that temporary when control flows over the ;. "
    You missed the "and then assign it" part.

    Quote Originally Posted by redneon
    For a shallow copy, you can just allow C++ to do it automatically like in my example, can't you?
    Yes.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Registered User
    Join Date
    Aug 2003
    Posts
    21
    Quote Originally Posted by laserlight View Post
    You missed the "and then assign it" part.
    Oops. So I did

    So, would...

    Code:
    class MyClass
    {
    	MyClass()
    	{
    		this = MyClass(1, 2);
    	}
    	
    	MyClass(int a, int b)
    	{
    		//Do some init.
    	}
    };
    ...essentially be doing the same thing?

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    It should be:
    Code:
    *this = MyClass(1, 2);
    Quote Originally Posted by redneon
    ...essentially be doing the same thing?
    The net effect should be the same unless the constructors and copy assignment operator have side effects, but the default constructor is potentially expensive. It is like... you are a baker who wants to bake a scrumptious cake, but you bake a plain cake and then replace what you baked with a scrumptious cake ordered from another baker. It would have been cheaper to use your own ingredients to bake your own scrumptious cake.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    Registered User
    Join Date
    Aug 2003
    Posts
    21
    Yeah, I know what you mean. I undertsand it's a bad idea. It's just something about C++ I was unclear on.

    I missed the dereference on the this pointer

Popular pages Recent additions subscribe to a feed