Thread: Calling an object's constructor?

  1. #1
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286

    Calling an object's constructor?

    Hello!

    I have a class mp_image, which looks something like this:
    Code:
    class mp_image {
        int w, h;
        byte* pixels; //byte is a typedef of uint8_t;
    public:
        mp_image()
        {
    	w = h = 0;
    	pixels = NULL;
        }
        mp_image(int width, int height)
        {
    	w = width;
    	h = height;
    	pixels = new byte[3*w*h];
        }
        ~mp_image()
        {
    	if (pixels) delete[] pixels;
        }
        mp_image& DownsampleNTimes(int n, mp_image& dest_image)
        {
    	/* Initialize dest_image here with width w/n and height h/n */
    
    	/* more code... */
    
    	return;
        }
    }
    It's a simplification, but anyway, I would like the member function DownsampleNTimes to take an object dest_image as an argument (by reference) to store the downsampled image in. dest_image must be an empty image (no need for calling it's destructor), and the function shall start by initializing the image so that the right amount of memory gets allocated for holding the pixels of the downsampled image. Is it possible to call the constructor (and even the destructor) of an object, or should objects always be refered to by pointers so that the constructors/destructor are called using the new/delete operators?
    Come on, you can do it! b( ~_')

  2. #2

    Join Date
    Apr 2008
    Location
    USA
    Posts
    76
    Well, if you're passing by reference, the parameter will be an object (that is, it will already be constructed). You can't call the constructor on an object and probably shouldn't call the destructor, because that will get called automatically when the object goes out of scope.

    Passing a pointer probably isn't a good idea either because then it's not guaranteed to point to an object.

    If I understand correctly, you probably don't need that parameter at all, you can just declare and construct the object withinin the function and return it (meaning it would have to be dynamically allocated unless you wanted to store it in a memory address which could be passed as a parameter, or return by value).

    You should also take advantage of initializer lists.
    Last edited by rudyman; 07-23-2008 at 07:58 PM.

  3. #3
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    If you can, instead write an init method that will initialize the object for you.

    It is possible to construct an object given a pointer to the memory that it will point to using placement new. But generally this is only used for generic allocators responsible for managing memory, not for late initialization of a class.

    Calling the destructor is possible, but it can only be done in cases where the destructor would not automatically get called, since then the system will try to destroy the object twice. Again using a destroy method or similar is often a better approach.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  4. #4
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286
    Quote Originally Posted by rudyman View Post
    You should also take advantage of initializer lists.
    How do you mean? Isn't initializer lists only for classes with other class objects as members? My class has no member which needs to be constructed.

    And King Mir, your suggestion seems like a good idea, thank you.
    Come on, you can do it! b( ~_')

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    You can do:
    Code:
        mp_image(int width, int height) 	: w(width), h(height);
        {
    	pixels = new byte[3*w*h];
        }
    You could also default width and height to zero and check if they either of them is zero in the mp_image constructor - then set pixels to NULL or allocate depending on the result. That way, you don't have to have two different constructors.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    The larch
    Join Date
    May 2006
    Posts
    3,573
    You might need to implement a copy constructor and overloaded assignment operator anyway (Rule of Three).

    Then you could simply do:
    Code:
    dest_image = mp_image(w/n, h/n);
    to resize the internal array of dest_image.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  7. #7
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> Isn't initializer lists only for classes with other class objects as members?
    No, it's for initializing all member variables. When your class has only built-in types as members it has no effect on performance, but you should still use it for consistency and clarity of code.

    BTW, why aren't you using a vector here? I can't think of any reason why a dynamic array would be better, and with vector you wouldn't have to worry about the rule of three.

  8. #8
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286
    Quote Originally Posted by anon View Post
    You might need to implement a copy constructor and overloaded assignment operator anyway (Rule of Three).

    Then you could simply do:
    Code:
    dest_image = mp_image(w/n, h/n);
    to resize the internal array of dest_image.
    I guess this would be an ordinary assignment? So I can overload only the assignment operator. But I guess I could define a copy function as well at the same time. By the way, is there any rule when to copy the data of the internal arrays (such as the pixel values in my case), whether the data should be copied into a new memory allcation or only refered to by another pointer? Does it differ between copying and assignment?
    Come on, you can do it! b( ~_')

  9. #9
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    It depends on what you're trying to do. If you make a copy, then changes to one will not affect the other. If you copy only the pointer, then changes to one will show up automatically in the other (because they point to the same data). Which is right for your program?

    The safest thing to do is to create new memory and copy the data to it (actually the safest thing to do is use vector to automate that task). This is probably more common in C++.

    If you just keep a copy of the pointer, then you have to keep track of all the copies so that delete is called on that memory only once. Your code above calls delete in the destructor, so if you copied the pointer only (which is what it does by default) then two different instances of the class would use the same pointer value and both would try to delete the array when they were destructed. That would be very bad.

    And using a vector would save you all this trouble.

  10. #10
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Write a swap function for an mp_image, construct the downsampled image into a temporary mp_image and swap it with dest_image before returning.
    Code:
        void swap(mp_image &other)
        {
    	std::swap(w, other.w);
    	std::swap(h, other.h);
    	std::swap(pixels, other.pixels);
        }
        mp_image& DownsampleNTimes(int n, mp_image& dest_image)
        {
    	mp_image temp(w/n, h/n); /* Initialize dest_image here with width w/n and height h/n */
    
    	/* more code... */
    
    	dest_image.swap(temp);
    	return dest_image;
        }
    Can't get much better than that!

    Using a vector and following the rule of three could also help.
    Last edited by iMalc; 07-25-2008 at 02:27 PM.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  11. #11
    Registered User
    Join Date
    May 2008
    Posts
    53
    Why are you making DownsampleNTimes a member function?

    --
    Computer Programming: An Introduction for the Scientifically Inclined

  12. #12
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286
    Quote Originally Posted by Sander View Post
    Why are you making DownsampleNTimes a member function?
    Because the heavy use of the member variables. Do you think it's a better idea making it extern?
    Come on, you can do it! b( ~_')

  13. #13
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286
    However, I got it working directly after I writing a assignment operator, as required in the rule of three. Thanks.
    Come on, you can do it! b( ~_')

  14. #14
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> Because the heavy use of the member variables.
    Are you using the member variables of the current object (this)? Or are you using the member variables of the passed in object dest_image? If it's the latter, then it doesn't need to be a regular member function, and should probably be either a static member function on non-member friend. A better solution might be to leave it a member function but perform the operation on the this object instead of taking a mp_image reference.

    >> However, I got it working directly after I writing a assignment operator, as required in the rule of three.
    I still think you should use vector.

  15. #15
    Registered User
    Join Date
    May 2008
    Posts
    53
    Quote Originally Posted by TriKri View Post
    Because the heavy use of the member variables. Do you think it's a better idea making it extern?
    Yes, like Daved said. I would assume that your image class also has some method to get at the pixel data (which you had elided for briefness). A reasonable rule of thumb is that if a function can be external to your class (perhaps a friend function, if need be) then it probably should.

    If you follow this rule of thumb, your data types will consolidate faster. This may not sound too important if you're working on a project all by yourself, but in multi-people projects it's very nice if your image.h header file stabilizes early on in the project, and needs infrequent changes.

    --
    Computer Programming: An Introduction for the Scientifically Inclined

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 10
    Last Post: 06-02-2008, 08:09 AM
  2. Replies: 60
    Last Post: 12-20-2005, 11:36 PM
  3. array of objects?
    By *~*~*~* in forum C++ Programming
    Replies: 4
    Last Post: 05-31-2003, 05:57 PM
  4. Calling constructor of the base class of a derived class..
    By CaptainPenguin in forum C++ Programming
    Replies: 5
    Last Post: 02-19-2003, 01:47 PM
  5. Can't find my constructor
    By Nippashish in forum C++ Programming
    Replies: 4
    Last Post: 12-06-2002, 08:17 PM