0

foo.h

#include "class1.h"

class foo{

    private:
        class1* class1ObjectPointer;
    
    public:
        foo();
        virtual ~foo();
    
        void foomethod();

}

foo.cpp (VERSION 1)

#include "foo.h"

foo::foo()
{
    this->class1ObjectPointer = new class1();
}


foo::~foo()
{
    if( this->class1ObjectPointer != NULL ){

        delete class1ObjectPointer;
        this->class1ObjectPointer = NULL;
    }
}


foo::foomethod(){

    *(this->class1ObjectPointer) = some_method(); 
    //suppose some method returns an object of class1

}

foo.cpp (VERSION 2)

#include "foo.h"

foo::foo()
{
    this->class1ObjectPointer = NULL;
}


foo::~foo()
{
    if( this->class1ObjectPointer != NULL ){

        delete class1ObjectPointer;
        this->class1ObjectPointer = NULL;
    }
}


foo::foomethod(){

    class1 object;
    object = some_method(); 
    //suppose some method returns an object of class1
    this->class1ObjectPointer = new class1(object); // copy constructor
}

Which pointer assignment is better in the following cases:

  1. objects of class1 always have fixed size (e.g. a class with fixed variables in it)
  2. objects of class1 may have members with variable size (e.g. a class that has a matrix in it which can potentially have different sizes)

Would you suggest any other and better way of doing what I did in these snippets?

Community
  • 1
  • 1
Matteo
  • 7,924
  • 24
  • 84
  • 129
  • What is your problem? It's not really clear what you are struggling with and what you are asking. – David Heffernan Mar 02 '12 at 15:13
  • @DavidHeffernan I need to create an object of `class1` which could have variable size, and don't know which way of allocating space for it is better. – Matteo Mar 02 '12 at 15:17
  • That thing in your code that you've identified as a copy constructor, is not a copy constructor. Copy constructors do not take pointers. – Benjamin Lindley Mar 02 '12 at 15:25
  • @BenjaminLindley doesn't a copy constructor take a reference to an object to copy as an input? – Matteo Mar 02 '12 at 15:29
  • @Matteo: Yes, but by prefixing your object with `&`, you are providing a pointer, not a reference. From the caller's perspective, a function that takes an argument by reference is indistinguishable from one that takes one by value. – Benjamin Lindley Mar 02 '12 at 15:32
  • @BenjaminLindley it's a typo..sorry – Matteo Mar 02 '12 at 16:04

3 Answers3

2

the instance of class has constant size regardless of any assignments. If you assign a member-variable to some pointer, the size of the instance will not change. Just some junk in memory (or NULL value if you had initialized it first) will be replaced by the address of some other allocated object.

Jurlie
  • 1,014
  • 10
  • 27
  • why is this? I thought that it would depend on the size of member variables it contains.. – Matteo Mar 02 '12 at 15:18
  • @Matteo But it always contains the same number of member variables, and those also always have the same size. In fact, the size of *any* type is (and **must**) be fixed at compile time. – Konrad Rudolph Mar 02 '12 at 15:19
  • 2
    @Matteo, Konrad Rudolph is right. Just look: pointer, like any other variable has fixed size (dependent on the system). And the data that is pointed by that pointer is not counted into object's size because it located somewhere in another place in memory. – Jurlie Mar 02 '12 at 15:26
2

It's probably better (more efficient, and easier to avoid memory leaks) to reassign the object per your first example than to allocate a new object - as demonstrated by the memory leak in your second example.

It looks very much like you don't need a pointer at all; just embed an object in your class:

class foo {
private:
    class1 class1Object;

public:
    // implicit constructors, assignment and destructor are fine
    void foomethod() {class1Object = some_method();}
};

Your second situation makes no sense - objects of a particular class are all the same size.

If you really do need to store a pointer (perhaps because you need polymorphism), then the simplest way to handle it is with a smart pointer:

class foo {
private:
    std::unique_ptr<class1> class1ObjectPointer;

public:
    foo() : class1ObjectPointer(new class1) {}
    // implicit copying and destructor are fine

    foomethod() {*class1ObjectPointer = some_method();}
    // or, if not assignable, class1ObjectPointer.reset(new class1(*some_method()));
};

If you really want to manage it yourself, then you'll need to override the default copy constructor and copy-assignment operator per the Rule of Three, make sure you delete the old object when reassigning the pointer, and be careful about exception safety. And there's no need to either check for NULL before deleting, or to assign NULL in the destructor.

Community
  • 1
  • 1
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • Actually the problem is that the class1 hasn't any method to set members of the class, and so I have some problems when I try to edit an object of that class, after having instantiated it. – Matteo Mar 02 '12 at 15:21
0
  1. the if ptr != NULL check is redundant in front of delete since it does the check internally.

  2. Which of these variants is better depends on the case. Both have their uses.

  3. Don’t use pointers here at all. If you have to, use std::unique_ptr (requires C++11) or boost::shared_ptr.

  4. In any case, members in constructors should be initialised, not assigned. That is, write it as follows:

    foo::foo() : class1ObjectPointer(new class1) { }
    

    This uses an initialisation list.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • What if you're not using Boost or C++11? Just curious. – Almo Mar 02 '12 at 15:16
  • @Almo Then you’re an idiot. :p Sorry – what I meant is: your project coordinator is one. There is no good excuse for not using certain Boost components, and `shared_ptr` is one of them. – Konrad Rudolph Mar 02 '12 at 15:18
  • @KonradRudolph Actually the problem is that the class1 hasn't any method to set members of the class, and so I have some problems when I try to edit an object of that class, after having instantiated it. – Matteo Mar 02 '12 at 15:21
  • @Almo: Even if some idiot has outlawed Boost, you've probably got `std::tr1::shared_ptr` (or `std::auto_ptr` as a last resort). – Mike Seymour Mar 02 '12 at 15:39
  • I work in an environment where every extra set of code we use incurrs issues with the legal department, so this sort of issue is important to me. :) – Almo Mar 02 '12 at 15:49
  • 1
    @Almo Whoa, I’m sorry for you. That said, clearing the Boost license, while certainly some work, should be feasible and worthwhile, and has only got to be done once. – Konrad Rudolph Mar 02 '12 at 15:51
  • I agree, it's probably worthwhile, but I would need a good reason, especially since we need both use and redistribution rights as we develop middleware and development tools. – Almo Mar 02 '12 at 15:59
  • @Almo: with Boost you would have both. In the worst cast, you can simply redevelop your own set of smart pointers (once) and then use them. I work in a company who did so, long before Boost existed. – Matthieu M. Mar 02 '12 at 16:03