C++ best practices (specific examples)

Started by
11 comments, last by DevFred 14 years, 1 month ago
Hey all I'm in the process of learning C++ and I have a few questions about how to do some specific stuff the right way. 1. Which is the better solution and why?

//somewhere an object is defined
MyClass t = MyClass(...);

//here's functions that operates on MyClass
void doStuffWithTable1(MyClass* t) {
   ...
   ...
}

// OR

void doStuffWithTable2(MyClass& t) {
   ...
   ...
}

2. Will this work? Why not and how to do it right?

//foo.h
...
std:vector<MyClass> classes;
...

//foo.cpp
...
Foo::Foo() {
   for(int i = 0; i < n; i++) {
       MyClass t(...);
       //do stuff with t
       classes.push_back(t);
   }
}
...

Will classes after this for-loop, contain n instances of MyClass?
Advertisement
1. First solution lets you pass NULL, second one does not, because a reference is just another name for an already existing object, so doStuffWithTable1 has to check, if a valid instance has been passed, while doStuffWithTable2 can safely assume the paramter is valid

2. Yep, I'm pretty sure this will work, but why don't you try it out yourself?
1) Use references instead of pointers when you can. They're (almost) guaranteed to be valid. Use pointers when you need the ability to pass NULL. Also, use const MyClass* and const MyClass& if you don't want to change the parameter inside the function.

2) Sure, why not? As long as MyClass copies correctly, that code should be fine.
Quote:Original post by Ariste
1) Use references instead of pointers when you can. They're (almost) guaranteed to be valid. Use pointers when you need the ability to pass NULL. Also, use const MyClass* and const MyClass& if you don't want to change the parameter inside the function.

2) Sure, why not? As long as MyClass copies correctly, that code should be fine.


IIRC const MyClass * was trickier, was not something like const MyClass *const varName?
Quote:Original post by Gammenon
Quote:Original post by Ariste
1) Use references instead of pointers when you can. They're (almost) guaranteed to be valid. Use pointers when you need the ability to pass NULL. Also, use const MyClass* and const MyClass& if you don't want to change the parameter inside the function.

2) Sure, why not? As long as MyClass copies correctly, that code should be fine.


IIRC const MyClass * was trickier, was not something like const MyClass *const varName?


No.

const T* is a pointer to const T. You can change the pointer (to point to a different object, to null) but not the pointee.

const T* const is a const pointer to const T. You can change neither the pointer nor the pointee.

const T* const is roughly equivalent to const T&.
[TheUnbeliever]
Quote:Original post by TheUnbeliever
Quote:Original post by Gammenon
Quote:Original post by Ariste
1) Use references instead of pointers when you can. They're (almost) guaranteed to be valid. Use pointers when you need the ability to pass NULL. Also, use const MyClass* and const MyClass& if you don't want to change the parameter inside the function.

2) Sure, why not? As long as MyClass copies correctly, that code should be fine.


IIRC const MyClass * was trickier, was not something like const MyClass *const varName?


No.

const T* is a pointer to const T. You can change the pointer (to point to a different object, to null) but not the pointee.

const T* const is a const pointer to const T. You can change neither the pointer nor the pointee.

const T* const is roughly equivalent to const T&.



If I have a const T*, I can call some not-const function, but with const & I cannot. Am I wrong?
Quote:Original post by Gammenon
Quote:Original post by TheUnbeliever
<snip>
No.

const T* is a pointer to const T. You can change the pointer (to point to a different object, to null) but not the pointee.

const T* const is a const pointer to const T. You can change neither the pointer nor the pointee.

const T* const is roughly equivalent to const T&.



If I have a const T*, I can call some not-const function, but with const & I cannot. Am I wrong?


I'm afraid so - you still have a const T as the pointee, so dereferencing the pointer allows you to do everything that you could do with a straight instance of (or reference to) const T but no more. So you can't modify it or call non-const member functions.
[TheUnbeliever]
Quote:Original post by Niux
1. Which is the better solution and why?


Use references when you can, and pointers when you have to.

The same goes for any conceivable thing that you could use instead of the pointer.

However, also consider implementing this as a member function:

void MyClass::doStuffWith() {  ...  ...}


Quote:
2. Will this work? Why not and how to do it right?


Do not define global variables in a header. You should declare them there, with 'extern', only if other source files will need to access them. Define the variable in the .cpp file.

Oh, you meant that 'classes' is a member of 'Foo'? Sure, that works fine then.

Quote:Will classes after this for-loop, contain n instances of MyClass?


Yes; that's what .push_back() is for.

However, do you really need to "do stuff with t" before putting it into the vector? What is "stuff" here?
Thanks for all the replies!

Quote:
Yes; that's what .push_back() is for.


Maybe I should have bin more specific in my question, however what I wanted to find out, was whether .push_back() would only put the reference in the vector and not copy the object. Meaning when the
Myclass t(...)
would go out of scope and be deleted, the reference would be invalid. But I probably should have thought about it one extra time, before asking, since classes is a vector of MyClass and not MyClass references.

Quote:
However, do you really need to "do stuff with t" before putting it into the vector? What is "stuff" here?


"Stuff" in this case is to initialize a member of MyClass with a random number. Now, this could be done in a constructor, but it is not really coherent with the class interface - using a setter method would be better in this case.

Another question I have;
When declaring members in the header file like this:
class MyClass {public:	MyClass();	virtual ~MyClass();private:        MyOtherClass o;};


I noticed that the default (MyOtherClass(void)) constructor is automatically called. I looked it up and it is an error not to initialise the object when declared, thus the automatic call to the default constructor. BUT what I want, and this is most likely a Java ting I shouldn't be doing in C++, is to just declare the member object (o), and later initialise it:
o = MyOtherClass(...);

The reason for initialising it later could be that the constructor arguments are not calculated when the header is loaded. So the question is what is the correct C++ way to do this ? Right now I just have a default constructor that does nothing and then later reassign the member variable.
Quote:Original post by Niux
what I wanted to find out, was whether .push_back() would only put the reference in the vector and not copy the object.

Whatever you give to push_back will be copied into the vector via the copy constructor.

Quote:Original post by Niux
since classes is a vector of MyClass and not MyClass references.

Note that there is no such thing as a vector of references. You probably meant a vector of pointers.

Quote:Original post by Niux
I noticed that the default (MyOtherClass(void)) constructor is automatically called.

Only if you don't initialize yourself in the initialization list:
MyClass() : o(...) // <--- initialization list{    // constructor body}

This topic is closed to new replies.

Advertisement