[offtopic]passing objects as parameters in c++

Hello folks,

I have been playing around with OF for a few days now and I hope you guys don’t mind me asking very n00b question. Basically I am trying to create a particle class and pass three parameters in the constructor which are ofxVec2f type.

The way I do is straightforward, in my testApp.h file I initiate my Particle object like:

  
Particle p;  

and in my .cpp file I am going like this:

  
  
	ofxVec2f loc = new ofxVec2f(0,0);  
	ofxVec2f vel = new ofxVec2f(0,0);  
	ofxVec2f acc = new ofxVec2f(0,0);  
	p = new Particle(loc, vel, acc);  
   

now this throws me errors. I am guessing I am making a mistake either with referencing the ofxVec2f objects or the way I instantiate them. I could initiate those ofxVec2f objects in the testApp.h header file as well but what’s holding me back is I need those objects in the local scope since in the future I am hoping to create multiple particles with different values. So I am wondering how would you go in that route.

I would appreciate any advices regarding this.
best,
ilteris

you’d need to define p as follows:

  
  
Particle *p;  
  

new always returns a pointer to the object that has been reserved on the heap.
and you’ll have to delete it after use. that’s one of the really annoying things about c++. you have to take care of the memory management yourself.

best
joerg

Hi, In your particle constructor definition, you either want to pass in pointers to ofxVec2f or a reference to ofxVec2f. Internally they both work in pretty much the same way (they pass in the address of the object instead of a copy of the whole object). But the syntax is quite different. The former is the old school C way, the latter is C++ and more like Java. The important thing to remember is:

if a variable is a pointer to an object (denoted with a * after the variable type), it stores only the address in memory of the object. And to access the data of the object it points to, you must either use the * again (e.g. (*myPointer).x ) or use the -> operator (myPointer->x)

if a variable is a reference to an object, it is still the address of the object, but you can access the data using the variable name directly (e.g. myReference.x).

The pointer way:

  
  
// constructor  
Particle::Particle(ofxVec2f *_loc, ofxVec2f* _vel, ofxVec2f *_acc) {  
   loc = _loc;  // these are pointers  
   vel = _vel;  
   acc = _acc  
  
   float xPosition = loc->x; // use -> syntax to access data in a pointer  
   float yPosition = loc->y;  
}  
  
// in testApp  
   ofxVec2f *loc = new ofxVec2f(0,0);   // note the * after the ofxVec2f, because the new operator returns a pointer.  
   ofxVec2f *vel = new ofxVec2f(0,0);  
   ofxVec2f *acc = new ofxVec2f(0,0);  
   p = new Particle(loc, vel, acc);   
  
//instead you could do:  
ofxVec2f loc;  // this creates the object directly, unlike Java you don't need to do use new to create one. Notice the lack of * after the variable type.  
ofxVec2f vel;  
ofxVec2f acc;  
  
// if you do the above, you must dereference the object to get its address to pass into the constructor:  
p = new Particle(&loc, &vel, &acc);  
  

If that was a bit confusing, you can skip pointers all together

  
  
 // constructor  
Particle::Particle(ofxVec2f &_loc, ofxVec2f& _vel, ofxVec2f &_acc) {  
   loc = _loc;  // these are references, not pointers  
   vel = _vel;  
   acc = _acc  
  
   float xPosition = loc.x;  // use . syntax to access data in a reference, just like a normal object  
   float yPosition = loc.y;  
}  
  
// in testApp  
ofxVec2f loc;  // this creates the object directly  
ofxVec2f vel;  
ofxVec2f acc;  
  
// you pass the object to the constructor, but the compiler will only pass the address. But this all happens transparent to you...  
p = new Particle(loc, vel, acc);  
  

Dunno if that was helpful in any way, pointers & references can be quite complex at the beginning, I recommend reading up on the topic…

ahh and of course the same gos for ofxVec2f *loc etc.
although it might be better to write something like:

  
  
ofxVec2f loc = ofxVec2f(0,0);  
  

if ofxVec2f supports copying… just try it without new.

best
joerg

thanks gentlemen!

memo your explanation made a lot of sense! Especially showing two different examples made the OOP-tutorial on the wiki crystal clear in my head now too. I did some c++ projects in the past but it has been a while and I needed this explanation. much respect.

p.s. great job on the ofXMSAPhysics addon. Looking forward to collision detection in that.

best,
ilteris.

http://www.klaweht.com
[/url]

that was an early call for victory… I am getting weird errors.

here is what I do:

  
  
  
//testApp.h  
	Particle p;  
  
//testApp.cpp  
       ofxVec2f loc =  ofxVec2f(0,0);  
	ofxVec2f vel =  ofxVec2f(0,0);  
	ofxVec2f acc =  ofxVec2f(0,0);  
	float r = 10;  
	p = new Particle(loc, vel, acc);  
// no matching function call to "Particle::Particle(ofxVec2f&,....)  
  
//particle.h  
	Particle(ofxVec2f *l, ofxVec2f *v, ofxVec2f *c);   
	  
	//variable  
	ofxVec2f* loc;  
	ofxVec2f* vel;  
	ofxVec2f* acc;  
  
// Particle.cpp  
Particle::Particle(ofxVec2f* _loc, ofxVec2f* _vel, ofxVec2f* _acc)  
{  
	loc = _loc;  
//error cannot convert 'ofxVec2f' to 'ofxVec2f*' in assignment.  
	vel = _vel;  
//error cannot convert 'ofxVec2f' to 'ofxVec2f*' in assignment.  
	acc = _acc;  
//error cannot convert 'ofxVec2f' to 'ofxVec2f*' in assignment.  
  
}//endfunction  
  

I am missing something here. I would appreciate any help!
I also have one more question. Is there any speed gains using pointers instead of references? I am used to java way of doing things and I am wondering if referencing wastes more resources.

ilteris.

Is there any speed gains using pointers instead of references? I am used to java way of doing things and I am wondering if referencing wastes more resources.

Nope, internally they are the same. The different is you cannot reassign references, i.e. they are a bit more limited but generally easier to use because they point to existing allocated memory.

Unfortunately you cannot get exact Java style syntax in C/C++. References in C++ are close, but not exactly the same. You cannot use the ‘new’ operator to allocate an object for a reference (unless you do so on the same line as the declaration, but ignore that for now). References in C++ have to point to something. They cannot be uninitialized - so they are safer, you’re never gonna get a null or uninitialized reference. Pointers can be assigned later, so they are more flexible, you can create the object whenever you want. So you have more control over memory usage and you can pass parameters to its constructor. But the downside is you have to check for and handle uninitialized or null pointers and crashes. They both get compiled to the same code though, so performance is the same, its just compile time checking which differs.

The code you want is:

  
  
//testApp.h  
   Particle *p;    // this needs to be a pointer, because you want to call 'new' and create it passing parameters to its constructor.  
  
//testApp.cpp  
   ofxVec2f loc =  ofxVec2f(0,0);  
   ofxVec2f vel =  ofxVec2f(0,0);  
   ofxVec2f acc =  ofxVec2f(0,0);  
   float r = 10;  
   p = new Particle(loc, vel, acc);  
// no matching function call to "Particle::Particle(ofxVec2f&,....)  
  
//particle.h  
   Particle(ofxVec2f &l, ofxVec2f &v, ofxVec2f &c); // define these as references, not pointers  
     
   //variable  
   ofxVec2f loc;    // define these as objects, not pointers  
   ofxVec2f vel;  
   ofxVec2f acc;  
  
// Particle.cpp  
Particle::Particle(ofxVec2f& _loc, ofxVec2f& _vel, ofxVec2f& _acc) // reference, not pointer  
{  
   loc = _loc;   // the objects are copied over      
   vel = _vel;  
   acc = _acc;  
}//endfunction   
  

In the constructor, _loc is the object, not the address, so the whole object will be copied over to loc when we do loc=_loc. which is good, because the object being passed in is a local variable and will be destroyed once the testApp::setup() function finishes. if Particle::loc was pointing to it, it would be garbage after the function ends.

The reason we have ofxVec2f& _loc in the Particle::Particle header and not just ofxVec2f _loc, is to pass the object by reference so only its address is passed, BUT _loc still refers to the object not the address. This is quicker because we dont have to do two copies (once from the temp local variable in testApp::setup() into the temp function parameter stack, and once again from the temp function parameter stack into Particle::loc)

I just read what I wrote, and it sounds quite confusing… so I hope I havent just confused you even more :stuck_out_tongue: there are so many ways of doing this…

In this case, I would actually advise against pointers altogether (for simplicity sake, not that theres anything wrong with using pointers). You can give Particle an init(ofxVec2f &l, ofxVec2f &v, ofxVec2f &c) function, and call that instead of new Particle(). It is safe, will run equally fast (actually, will run an incy wincy fraction of a nanosecond faster because calling particle.doSomething() is an incy wincy fraction of a nanosecond faster than particle->doSomething()). So you don’t need any pointers or references at all. The only thing you should pay attention to, is pass objects by reference in function parameters. So instead of defining a function as :

  
  
init(ofxVec2f l, ofxVec2f v, ofxVec2f c);  // this will copy the whole object onto the stack - slow!  
  

use:

  
  
init(ofxVec2f &l, ofxVec2f &v, ofxVec2f &c);  // this will pass the objects address, but inside the function l, v, c will appear as objects, not pointers. Like Java.  
  

Hey ilteris long time no see!!

I just wanted to make a quick note on using a pointer for the particle instance. Unless you have a good reason its probably easier to not use a pointer but a plain stack object. I generally like to avoid pointers and OF has a tradition of doing that too.

To instance a stack object you generally just say:

Particle p = Particle( loc, vel, acc );

Very often, though, you want the instance to be a member of the testApp. In this case the default constructor is already called when the testApp is instanced. So you can’t instance it again.

For this reason there is a common pattern. It’s used all over OF. You use a separate initializer function. E.g for ofImage has loadImage(…), for ofxVec2f has set(…) In case of Particle you could add one and call it init(ofxVec2f& loc, ofxVec2f& vel, ofxVec2f& acc)

There are some cases where pointer are useful but surprisingly often you can write simpler code by using stack objects (and use references when you pass them around).

Though that might be useful,

/stefan

hey guys, thanks a lot for the heads up! memo thanks a lot for the detailed information. Things are more clear in my head now. I need to take a little break and will just jump back on the code once I have my dinner.

Stefan! I hope you are doing well, man. I am trying to get back into this mess again as you can see :slight_smile: Thanks for the tip regarding the structure. Definitely makes sense.

I still have your airport express card too! It’s in my drawer!!

alright I’ll catch you guys later

aright I am the official dumb of this thread. I still cannot compile this code properly with its shape below:

  
//testapp.h  
Particle p;  
//testapp.cpp  
        ofxVec2f loc =  ofxVec2f(0,0);  
	ofxVec2f vel =  ofxVec2f(0,0);  
	ofxVec2f acc =  ofxVec2f(0,0);  
	float r = 10;  
	p.init(&loc, &vel, &acc);  
       //error:no matching function for call to   
       // 'Particle::init(ofxVec2f*,ofVec2f*,ofxVec2f*)'  
       //ugh? I thought I declare this function in the header.   
  
//particle.h  
	//constructor  
	Particle();   
	  
	//methods  
	void init(ofxVec2f &l, ofxVec2f &v, ofxVec2f &c);  
	void update();  
	  
	void draw();  
  
	  
	//variable  
	ofxVec2f loc;  
	ofxVec2f vel;  
	ofxVec2f acc;  
	  
	float r;   
  
//particle.cpp  
Particle::Particle()  
{  
}//endfunction  
  
void Particle::init(ofxVec2f &_loc, ofxVec2f &_vel, ofxVec2f &_acc)  
{  
	loc = _loc;  
	vel = _vel;  
	acc = _acc;  
	r = 10;	  
}  

ahem :slight_smile:

http://forum.openframeworks.cc/t/particles-based-on-daniel-shiffman’s-teaching/1068/0

  
  p.init(&loc, &vel, &acc);   
  

needs to be

  
  
   p.init(loc, vel, acc);   
  

by putting & in the function call, you are taking the address of the objects and explicitly passing just the address, i.e. a pointer. whereas you defined Particle::init to not take pointers, but take references.
By putting & in the function definition you are saying ‘expect to be passed whole objects, not pointers, but even though you are passed the whole object, just pass the address anyway, and on the other side treat it as a normal object again not a pointer’.

So the idea of passing objects by reference is that you put & in the function definition, and never again have to worry about pointers, de-referencing or referencing, its all done in the background…

interesting topic :slight_smile:
pointers can be really confusing. so as a general rule, unless i’m dealing with big objects i just try to avoid using them altogether, or use them just to pass references around and not to really create new objects.

and also in terms of performance, its faster to allocate objects in the stack than allocating dynamic memory.

thanks a lot for your patience memo!

Finally, I got it working :slight_smile: