Basic C++ question
-
Nope. They don't do the same thing.
@
Workout workout1 (....);
@There you have the object already created (instantiated). You can directly use it.
With
@
Workout *workout2 = new Workout(…);
@You do the same thing but the access it different (and the memory is in different places).
if you use "*workout2" from the second version is the same as using "workout1".
Handing them to a routine using referencing or pointer is different:
@
void foo1 ( const Workout & workout )
{}
void foo2 ( Workout & workout )
{}
void foo3 ( Workout * workout )
{}
void main ()
{
Workout workout1(...);
Workout *workout2;
Workout *workout3;workout3 = &workout1; // you get the memory address and // assign to pointer workout2 = new Workout (...); // assigns memory foo1 ( workout1 ); foo2 ( workout1 ); foo3 ( &workout1 ); foo1 ( *workout2 ); foo2 ( *workout2 ); foo3 ( workout2 ); foo1 ( *workout3 ); foo2 ( *workout3 ); foo3 ( workout3 );
}
@In your code where the error is you basically do:
@
foo1 ( workout3 ); // compile error
foo2 ( workout3 ); // compile error
foo3 ( workout3 ); // this is ok, since as above
@Probably best is to go through the tutorial. Afterwards you may want to make a small program and try out systematically the different ways of instantiating and referencing to functions.
Basically you can do with such code as above, but this might overwhelm you by complexity.Good luck
-
[quote author="maximus" date="1380746647"]
I'm starting doing the tutorial, hopefully it will clear up stuff for me!
The main thing that confuse me is that I don't see the difference between instantiating an object, and declaring a pointer to an object. both don't do the same thing? i.e: those 2 line of code below:Workout workout = new Workout(..)
Workout *workout = new Workout(...)[/quote]
Among other reasons, "polymorphism" can only done with pointers
http://www.cplusplus.com/doc/tutorial/polymorphism/ -
Thanks for your help guys, and the great example!
I read the tutorial and it's much clearer now:
http://www.cplusplus.com/doc/tutorial/
http://www.youtube.com/playlist?list=PL2D1942A4688E9D63Good luck :)
-
My program run fine when I use approach #1
But since I know the data size before execution, I want to remove the "new" so that memory is not a problem. In the final version, I want to have a fixed amount of "Workout" and some more that the user can add, for those one I will use the "new" method.#1
@ QList<Interval*> lstInterval;
Interval *interval = new Interval(.5, 80, 90, 150, Interval::WARM_UP);
Interval *interval2 = new Interval(.5, 90, 80, 120, Interval::RECOVERY);
Interval *interval22 = new Interval(5, 95, 70, 100, Interval::COOLDOWN);
lstInterval.append(interval);
lstInterval.append(interval2);
lstInterval.append(interval22);
Workout *work = new Workout(lstInterval, "name", "me", Workout::ENDURANCE);
lstWork.append(work);@I have tried this conversion :
#2
@ QList<Interval*> lstInterval;
Interval interval(.5, 80, 90, 150, Interval::WARM_UP);
Interval interval2(.5, 90, 80, 120, Interval::RECOVERY);
Interval interval22(8, 95, 70, 100, Interval::COOLDOWN);
lstInterval.append(&interval);
lstInterval.append(&interval2);
lstInterval.append(&interval22);
Workout work(lstInterval, "name", "me", Workout::ENDURANCE);
lstWork.append(&work);@But this one fail at execution, for me both methods are supposed to do the same thing, am I missing something?
WORKOUT.H
@#ifndef WORKOUT_H
#define WORKOUT_H#include <QString>
#include <QList>
#include "interval.h"class Workout
{public:
enum Type
{
TEMPO,
ENDURANCE
};Workout(QList<Interval*> lstInterval, QString name, QString createdBy, Type type);
// ~Workout(); TODO
QList<Interval*> getLstInterval(); QString getName(); QString getCreatedBy(); QString getTypeToString(); Type getType(); int getMaxPower(); int getNbInterval(); double getTotalLength();
private :
QList<Interval*> lstInterval; QString name; QString createdBy; Type type; int maxPower; double totalLength;
};
#endif // WORKOUT_H@
WORKOUT.CPP
@#include "workout.h"
#include <QDebug>Workout::Workout(QList<Interval*> lstInterval, QString name, QString createdBy, Type type) {
this->lstInterval = lstInterval; this->name = name; this->createdBy = createdBy; this->type = type; this->totalLength = 0; this->maxPower = 0; foreach(Interval *val, this->lstInterval) { this->totalLength += val->getLength(); if (val->getTargentFTP() > this->maxPower) { this->maxPower = val->getTargentFTP(); } } qDebug() << "TotalLength" << this->totalLength; qDebug() << "MaxPower" << this->maxPower;
}
// -------------------------------------------
QList<Interval*> Workout::getLstInterval() {
return this->lstInterval;
}QString Workout::getName() {
return this->name;
}
QString Workout::getCreatedBy() {
return this->createdBy;
}
Workout::Type Workout::getType() {
return this->type;
}
QString Workout::getTypeToString() {
if (this->type == Workout::ENDURANCE ) {
return "Endurance";
}
else if (this->type == Workout::TEMPO) {
return "Tempo";
}
else
return "Workout type not defined";
}
int Workout::getMaxPower() {
return this->maxPower;
}
int Workout::getNbInterval() {
return this->lstInterval.size();
}
double Workout::getTotalLength() {
return this->totalLength;
}@ -
bq. But since I know the data size before execution, I want to remove the “new” so that memory is not a problem
you use dynamic objects not just for memory management but also for speed by avoiding a lot of wasting copy operations ... if you really switched to C++ then let the pointers be your friends :) , you cannot really benefit of C++ without pointers
to your issue in method #2 I think you go out of scope with your lists and the addresses will point out to some "destroyed" objects, as with "new" they persist in dynamic memory(heap) till they are destroyed ... and by the way I cannot see any code deleting the dynamic objects and freeing memory though, perhaps you have some memory leak
some more hints: put your seters and geters in class declaration and they will be inlined and the code execution will be little faster, and I use to return a reference to list members in a class to avoid again a copy
operation, as Workout::getLstInterval()Cheers!
-
Thanks for your hints mister!
Not so easy to switch from Java to C++ so all tips are appreciated :)I was afraid of using dynamic memory because I read it can generate exceptions and you need to check every time you do a "new" that it has been successful.
As for deleting the dynamic objects, this QList of <Workout*> will never be deleted, it is part of my MainWindow(Main program) and it needs to be there at all time, it will eventually grow or shrink depending on user operation.
When you say to put seters and geters in class declaration, you mean implement them directly in the header file ?
to return a reference to list member, I need to return a pointer right?
so instead of
QList<Interval*> getLstInterval();
I would use
QList<Interval*> * getLstInterval();
To return a QList pointer that point to many pointers of type Interval?
Can get confusing fast heheMerci!
-
maximus, handle the resources(memory, file, mutex) in c++ is pretty simple with the helps of standard library, exactly, I found it is much more easier to handle resource than any language come with garbage collector I know.I strongly suggest you study what is "RAII", this could make your life much more easier when developing with c++.
Also, QList<T> will handle the resource of T automatically atleast it is storing a raw pointer which hold onto some resources.
Example 1 : handle resource by containers
@std::vector<Interval> A;@
This one will be destroy when it is out of scope
If you don't need pointer, I would recommend the style of example 1Example 2 : handle resource by raw pointer and container
@
std::vector<*Interval> A;
A.emplace_back(new interval);
A.emplace_back(new interval);
......
for(auto data : A)
{
delete data;
}
@
you need to destroy the resource in exmaple 2example 3: handle resource by container and smart pointer
@
std::vector<std::uqniue_ptr<Interval>> A;
A.emplace_back(new Interval);
@
don't need to release the resource by yourself in example 3
if you need the power of pointer I would recommend solution 3There are different smart pointer in the standard, pick one which suit
your job most.In modern c++(not c with classes), resource management is a piece of cake(atleast
you are building some infrastructure like containers, smart pointer and so on),make
sure you are learning the c++ with modern way which proposed by Bjarne(father of c++),
herb, Lippman and other c++ gurus, stay away from "c with classes", this will help you develop
better quality, higher performance codes.If you want to have a solid foundation about c++, please give c++ primer 5 edition(not previous version)
a look, you only need to study chapter 1~16, it is enough for application developers.ps : RAII is same as "let the class to handle the resources "
-
[quote author="maximus" date="1381270434"]Thanks for your hints mister!
Not so easy to switch from Java to C++ so all tips are appreciated :)I was afraid of using dynamic memory because I read it can generate exceptions and you need to check every time you do a "new" that it has been successful.
As for deleting the dynamic objects, this QList of <Workout*> will never be deleted, it is part of my MainWindow(Main program) and it needs to be there at all time, it will eventually grow or shrink depending on user operation.
When you say to put seters and geters in class declaration, you mean implement them directly in the header file ?
to return a reference to list member, I need to return a pointer right?
so instead of
QList<Interval*> getLstInterval();
I would use
QList<Interval*> * getLstInterval();
To return a QList pointer that point to many pointers of type Interval?
Can get confusing fast heheMerci![/quote]
There are another way to get the reference of the object in c++
@
QList<Interval>& getLstInterval();
@What are the difference between & and pointer(*)?
1 : the way to access the variable
@
int max(int *a, int *b)
{
return *a > *b ? *a : *b;
}
@@
int max(int &a, int &b)
{
return a > b ? a : b;
}
@you access the reference like normal variable
2 : you can't change the address of the reference
@
int a = 3;
int *ptr = &a;
std::cout<<*ptr<<std::endl; //output 3
int b = 4;
ptr = &b; //now ptr point to the address of b
std::cout<<*ptr<<std::endl; //output 4
@@
int a = 3;
int &ref = a;
std::cout<<ref<<std::endl; //3
int b = 4;
ref = 4; //compile time error, you can't point to another address by reference
@please study c++ primer 5 edition from ch1~ch16
This could save you a lot of times--to debug and maintain your codes -
Thank you.
If I understand correctly , some smart pointers act like Java object, when no reference exist to an object, the object is deleted.
I just question why this isn't the normal behavior of C++ pointer, because typing every time really add some unnecessary syntax to the code. /Java rant over :)
So I will flush all my "standard" pointer and use the one in the list below depending on the use case.
Local variables: auto_ptr
Class members: Copied pointer std::unique_pt
STL Containers Garbage collected pointer (e.g. reference counting/linking) shared_ptr
Explicit ownership transfer Owned pointer -
[quote author="maximus" date="1381325557"]
I just question why this isn't the normal behavior of C++ pointer, because typing every time really add some unnecessary syntax to the code. /Java rant over :)
[/quote]As far as I know, there are two reasons
1 : for efficiency, runtime performance of c++ can't lower than c, this is one of the most important foundation of c++.Whatever, c++ is a high level system programming language, it most provide us full choices between abstraction and performance(the power close to the metal).
2 : destructor make c++ more difficult to support implicit garbage collector.
3 : (just my guess), it is not that important for many c++ programmers.
Although the standard committee do want to support garbage collector, but I don't know when this will come true.Even it do support, I think I wouldn't need it in most of the times, RAII is easy enough for me, and I like to know the life times of the resources.
The beauty of RAII compare to garbage collector is RAII can handle "any" resource(ex : mutex, file system and so on).
[quote author="maximus" date="1381325557"]
Local variables: auto_ptr
Class members: Copied pointer std::unique_pt
STL Containers Garbage collected pointer (e.g. reference counting/linking) shared_ptr
Explicit ownership transfer Owned pointer[/quote]1 : Please forget about auto_ptr, it is deprecated, just use unique_ptr if you need to hold a single entity of the object.
2 : unique_ptr can't copied, it can move only
@
std::unique_ptr<T> A(new T);
std::unique_ptr<T> B = A //oh, compile time error
@@
std::unique_ptr<T> A(new T);
std::unique_ptr<T> B = std::move(A); //ok, we move it
@move means "B steal the resource hold by A"
the logic under the is like this
@
int num = 10;
int *A = #
int *B = A;
A = nullptr;
@
B point to the address of A, so B have the resource of A held.
no memory allocation, this is fast and safe(wouldn't throw any exception)3 : shared_ptr, as the name show, it can shared the same object(reference count technique), do remember the trap of "circular dependency" when using shared_ptr.
"How to avoid memory leak by shared_ptr":http://stackoverflow.com/questions/1826902/how-to-avoid-memory-leak-with-boostshared-ptr4 : If you don't need the power of pointer(like runtime polymorphism), you could just use containers to store your resource.
@
std::vector<T> A(10); //allocate 10 T(some sort of object)
@5 : why so many smart pointer?
Because there are no silver bullet to guard the resource(especially when you want to provide the users best performance).There are too many different between java and c++, please spend some times to study c++ primer 5(ch1~ch16) if you want to develop high quality, good performance applications by c++.
c++ is a multi-paradigm language, it support OOP, procedural, stl, generic programming(not the same as the java generic, in c++, java generic is almost equal to dynamic polymorphism), template meta programming(ignore it if you don't need to develop something like boost),functional programming.
"learning c++ properly(not c with classes)":http://programmers.stackexchange.com/questions/48401/learning-c-properly-not-c-with-classes