I've mostly only worked with C and am running into some unfamiliar issues in C++.
Let's say that I have some function like this in C, which would be very typical:
int some_c_function(const char* var)
{
if (var == NULL) {
/* Exit early so we don't dereference a null pointer */
}
/* The rest of the code */
}
And let's say that I'm trying to write a similar function in C++:
int some_cpp_function(const some_object& str)
{
if (str == NULL) // This doesn't compile, probably because some_object doesn't overload the == operator
if (&str == NULL) // This compiles, but it doesn't work, and does this even mean anything?
}
Basically, all I'm trying to do is to prevent the program from crashing when some_cpp_function() is called with NULL.
What is the most typical/common way of doing this with an object C++ (that doesn't involve overloading the == operator)?
Is this even the right approach? That is, should I not write functions that take an object as an argument, but rather, write member functions? (but even if so, please answer the original question)
Between a function that takes a reference to an object, or a function that takes a C-style pointer to an object, are there reasons to choose one over the other?
Basically, all I'm trying to do is to
prevent the program from crashing when
some_cpp_function() is called with
NULL.
It is not possible to call the function with NULL. One of the purpose of having the reference, it will point to some object always as you have to initialize it when defining it. Do not think reference as a fancy pointer, think of it as an alias name for the object itself. Then this type of confusion will not arise.
A reference can not be NULL. The interface makes you pass a real object into the function.
So there is no need to test for NULL. This is one of the reasons that references were introduced into C++.
Note you can still write a function that takes a pointer. In this situation you still need to test for NULL. If the value is NULL then you return early just like in C. Note: You should not be using exceptions when a pointer is NULL. If a parameter should never be NULL then you create an interface that uses a reference.
A C++ reference is not a pointer nor a Java/C# style reference and cannot be NULL. They behave as if they were an alias to another existing object.
In some cases, if there are bugs in your code, you might get a reference into an already dead or non-existent object, but the best thing you can do is hope that the program dies soon enough to be able to debug what happened and why your program got corrupted.
That is, I have seen code checking for 'null references' doing something like: if ( &reference == 0 ), but the standard is clear that there cannot be null references in a well-formed program. If a reference is bound to a null object the program is ill-formed and should be corrected. If you need optional values, use pointers (or some higher level construct like boost::optional), not references.
As everyone said, references can't be null. That is because, a reference refers to an object. In your code:
// this compiles, but doesn't work, and does this even mean anything?
if (&str == NULL)
you are taking the address of the object str. By definition, str exists, so it has an address. So, it cannot be NULL. So, syntactically, the above is correct, but logically, the if condition is always going to be false.
About your questions: it depends upon what you want to do. Do you want the function to be able to modify the argument? If yes, pass a reference. If not, don't (or pass reference to const). See this C++ FAQ for some good details.
In general, in C++, passing by reference is preferred by most people over passing a pointer. One of the reasons is exactly what you discovered: a reference can't be NULL, thus avoiding you the headache of checking for it in the function.
You can use a special designated object as the null object in case of references as follows:
class SomeClass {
public:
int operator==(SomeClass &object) {
return (this == &object);
}
static SomeClass NullObject;
};
SomeClass SomeClass::NullObject;
void print(SomeClass &val) {
if(val == SomeClass::NullObject)
printf("\nNULL");
else
printf("\nNOT NULL");
}
You should use NULL only with pointers. Your function accepts a reference and they can't be NULL.
Write your function just like you would write it in C.
C++ references naturally can't be null, you don't need the check. The function can only be called by passing a reference to an existing object.
What is the most typical/common way of doing this with an object C++ (that doesn't involve overloading the == operator)?
Is this even the right approach? ie. should I not write functions that take an object as an argument, but rather, write member functions? (But even if so, please answer the original question.)
No, references cannot be null (unless Undefined Behavior has already happened, in which case all bets are already off). Whether you should write a method or non-method depends on other factors.
Between a function that takes a reference to an object, or a function that takes a C-style pointer to an object, are there reasons to choose one over the other?
If you need to represent "no object", then pass a pointer to the function, and let that pointer be NULL:
int silly_sum(int const* pa=0, int const* pb=0, int const* pc=0) {
/* Take up to three ints and return the sum of any supplied values.
Pass null pointers for "not supplied".
This is NOT an example of good code.
*/
if (!pa && (pb || pc)) return silly_sum(pb, pc);
if (!pb && pc) return silly_sum(pa, pc);
if (pc) return silly_sum(pa, pb) + *pc;
if (pa && pb) return *pa + *pb;
if (pa) return *pa;
if (pb) return *pb;
return 0;
}
int main() {
int a = 1, b = 2, c = 3;
cout << silly_sum(&a, &b, &c) << '\n';
cout << silly_sum(&a, &b) << '\n';
cout << silly_sum(&a) << '\n';
cout << silly_sum(0, &b, &c) << '\n';
cout << silly_sum(&a, 0, &c) << '\n';
cout << silly_sum(0, 0, &c) << '\n';
return 0;
}
If "no object" never needs to be represented, then references work fine. In fact, operator overloads are much simpler because they take overloads.
You can use something like boost::optional.
Related
I have spent a great deal of time programming in Java and a decent amount of time writing c++, but I have run into an issue I haven't been able to solve. In a Java class I can simply write the following,
public void doOperation(object a)
{
if(a != this)
{
set(a); // just some method that sets this.a = object.a
}
doOperation();
}
public void doOperation()
{
this.a = pow(this.a,3);
}
The part I am having trouble implementing in c++ is the if statement where I check if the argument object is equal to this. I have tried this in c++
object::doOperation(object a)
{
if(a != this)
{
set(a);
}
doOperation();
}
object::doOperation()
{
this->a = pow(this->a,3)
}
The error I get reads, "no match for ‘operator!=’ (operand types are ‘object’ and ‘object* const’)". Thanks in advance for anybody who can help!
You can simply pass "a" by reference, take a pointer to "a" and compare it with "this", like so:
object::doOperation(object & a)
{
if(&a != this)
{
set(a);
}
doOperation();
}
object::doOperation()
{
this->a = pow(this->a,3)
}
This is a standard way that people would e.g. implement copy assignment operators in C++. It's not always done this way, but often the implementation of that will take a const reference to an object, and use a check against "this" to prevent self assignment.
Edit: Let me try to take a broader view, which might be more useful to you.
In Java, objects are implicitly passed around by reference and not by value, and they are garbage collected also, automatically destroyed when no-one needs them anymore.
The closest way to get that kind of semantics in C++ is to pass around std::shared_ptr<A> when in java you would have passed A. Then, when you need to compare against this, you can use the get method to get a raw pointer from the shared pointer and compare it literally against this. OR, if you use the std::enable_shared_from_this template when you define your class, you can use shared_from_this to get a shared_ptr<A> to this at any point in your member functions, and compare the shared_ptr's directly.
I'm assuming you are using C++11, otherwise you would use boost headers for that stuff.
Note also the stuff about "weak_ptr" which you might need to use if you have cyclic references.
That's because this is a pointer type in C++. If your function signature would use a pointer as well, it would work:
object::doOperation(object* a)
{
if(a != this)
{
set(a);
}
doOperation();
}
In Java most objects are passed around as references. To avoid aliasing problems you may then need to check for reference equality: are these two apparently distinct objects, really distinct, or do the references refer to the same object?
In C++ objects are often passed as values, copying their values. And for values it doesn't make sense to check for object identity. E.g. a function argument passed by value, as in your object::doOperation(object a) example, will always have an address different from everything else at that point in the program execution (it's freshly allocated).
Still there are some cases where objects are passed by reference (or pointer), and where self-check is appropriate.
For example, a copy assignment operator might go like this:
auto My_class::operator=( My_class const& other )
-> My_class&
{
if( &other != this )
{
values_ = other.values_; // Avoid this work for self-assign.
}
return *this;
}
The self-check can also be crucial for correctness, although with use of standard library containers and smart pointers correctness can usually be ensured without any self-check.
If an object has been passed by value as in
void object::doSomething(object x)
{
// whatever
}
then it is not necessary to compare with this. Even of the caller does
some_object.doSomething(some_object);
the x is a temporary copy - i.e. so a different object is guaranteed.
If the argument is passed by reference or argument then remember that this is a pointer and not a reference (unlike Java in which those concepts are entwined), for example;
void object::doSomething(object *x)
{
if (this != x)
{
}
}
and
void object::doSomething(object &x)
{
if (this != &x)
{
}
}
The latter assumes that object does not have an interfering operator&(). If that assumption is invalid then, in C++11 use addressof(x) (where addressof() is specified in <memory>. Before C++11, the tricks to get address of x are a little more indirect (e.g. a sequence of casts).
Personally, I don't do such tests at all. Instead, I simply do
void object::doSomething(object &x)
{
object temp(x);
// do things with temp and *this
std::swap(x, temp);
}
which relies on working copy semantics, but also gives more exception safety. If a class makes the above prohibitive, then that is more usually a problem with class design (better to find another way to avoid the need to compare with this).
If a C++ class member function requires a pointer to an object as an argument, is it considered bad practice to pass by reference?
The following code, for example, will work, however without the pass by reference it becomes a dangerous code, and will lead to catastrophic errors at runtime.
class ClassA
{
public:
void SetPointer(const ClassB& classb) // Remove 1 ampersand and serious errors will occur
{
if(ptr_to_classb == nullptr) // Initialized to nullptr in constructor
ptr_to_classb = &classb;
else
throw(...); // Throw some error
}
private:
ClassB* ptr_to_classb;
}
Consider if passing by value, and a copy of the argument was made, that this would be disastrous when dereferencing at a later time.
The alternative is this:
class ClassA
{
public:
void SetPointer(const ClassB* const classb)
{
if(ptr_to_classb == nullptr) // Initialized to nullptr in constructor
ptr_to_classb = (ClassB*)(classb);
else
throw(...); // Throw some error
}
private:
ClassB* ptr_to_classb;
}
I like consistency, to defaulted to the first type, however I suspect that the second form is considered to be better practice. Is this the case?
Well, both approaches are correct and fine but in your case it will be probably better to go with pointers, since a reference variable can only be assigned a value at initialization unlike pointers. With the same pointer you could later pass a different class object.
My view is that if passing a null argument to the method is a valid thing to do (i.e. the logic that the method executes would be valid with a null pointer), then use a pointer. If the argument should never be null then use a reference.
In your case this depends on whether it is valid for ClassA::ptr_to_classb to be null. Since you throw if ptr_to_classb is already set (meaning you don't ever want to change what it points to) you might even want to conside storing a reference instead and passing that in the constructor of ClassA, getting rid of ClassA::SetPointer.
There are some other opinions on reference vs pointer here as well.
Your method just sets a field of your object, so it seems you want to use the type of the field (which is pointer, not reference). You wrote
I like consistency, to defaulted to the first type
which, I guess, refers to the rule "use references when possible; use pointers oterwise". I think your case is an exception from this rule, because the declaration
void do_stuff(ClassA& object)
usually means "do stuff on the object, and forget about it", and your case is different.
In a couple of my older code projects when I had never heard of smart pointers, whenever I needed to check whether the pointer still pointed to a valid object, I would always do something like this...
object * meh = new object;
if(meh)
meh->member;
Or when I needed to delete the object safely, something like this
if(meh)
{
delete meh;
meh = 0;
}
Well, now I have learned about the problems that can arise from using objects and pointers in boolean expressions both with literal numbers, the hard way :. And now I've also learned of the not so new but pretty cool feature of C++, the nullptr keyword. But now I'm curious.
I've already gone through and revised most of my code so that, for example, when deleting objects I now write
if(meh)
{
delete meh;
meh = nullptr;
}
Now I'm wondering about the boolean. When you pass just say an int into an if statement like this,
int meh;
if(meh)
Then it implicitly checks for zero without you needing to write it.
if(meh == 0) // does the exact same check
Now, will C++ do the same for pointers? If pass in a char * like this to an if statement?
char * meh;
if(meh)
Then will it implicitly compare it with nullptr? Because of how long I have been writing these ifs like this, it is second nature at this point to check if the pointers valid before using by typing if (object *) and then calling its members. If this is not the functionality why not? Too difficult to implement? Would solve some problems by removing yet another tiny way you could mess up your code.
In C, anything that's not 0 is true. So, you certainly can use:
if (ptrToObject)
ptrToObject->doSomething();
to safely dereference pointers.
C++11 changes the game a bit, nullptr_t is a type of which nullptr is an instance; the representation of nullptr_t is implementation specific. So a compiler may define nullptr_t however it wants. It need only make sure it can enforce proper restriction on the casting of a nullptr_t to different types--of which boolean is allowed--and make sure it can distinguish between a nullptr_t and 0.
So nullptr will be properly and implicitly cast to the boolean false so long as the compiler follows the C++11 language specification. And the above snippet still works.
If you delete a referenced object, nothing changes.
delete ptrToObject;
assert(ptrToObject);
ptrToObject = nullptr;
assert(!ptrToObject);
Because of how long I have been writing these ifs like this, it is second nature at this point to check if the pointers valid before using by typing if (object *) and then calling it's members.
No. Please maintain a proper graph of objects (preferably using unique/smart pointers). As pointed out, there's no way to determine if a pointer that is not nullptr points to a valid object or not. The onus is on you to maintain the lifecycle anyway.. this is why the pointer wrappers exist in the first place.
In fact, because the life-cycle of shared and weak pointers are well defined, they have syntactic sugar that lets you use them the way you want to use bare pointers, where valid pointers have a value and all others are nullptr:
Shared
#include <iostream>
#include <memory>
void report(std::shared_ptr<int> ptr)
{
if (ptr) {
std::cout << "*ptr=" << *ptr << "\n";
} else {
std::cout << "ptr is not a valid pointer.\n";
}
}
int main()
{
std::shared_ptr<int> ptr;
report(ptr);
ptr = std::make_shared<int>(7);
report(ptr);
}
Weak
#include <iostream>
#include <memory>
void observe(std::weak_ptr<int> weak)
{
if (auto observe = weak.lock()) {
std::cout << "\tobserve() able to lock weak_ptr<>, value=" << *observe << "\n";
} else {
std::cout << "\tobserve() unable to lock weak_ptr<>\n";
}
}
int main()
{
std::weak_ptr<int> weak;
std::cout << "weak_ptr<> not yet initialized\n";
observe(weak);
{
auto shared = std::make_shared<int>(42);
weak = shared;
std::cout << "weak_ptr<> initialized with shared_ptr.\n";
observe(weak);
}
std::cout << "shared_ptr<> has been destructed due to scope exit.\n";
observe(weak);
}
Now, will C++ do the same for pointers? If pass in a char * like this to an if statement?
So to answer the question: with bare pointers, no. With wrapped pointers, yes.
Wrap your pointers, folks.
It's not possible to test whether a pointer points to a valid object or not. If the pointer is not null but does not point to a valid object, then using the pointer causes undefined behaviour. To avoid this sort of error, the onus is on you to be careful with the lifetime of objects being pointed to; and the smart pointer classes help with this task.
If meh is a raw pointer then there is no difference whatsoever between if (meh) and if (meh != 0) and if (meh != nullptr). They all proceed iff the pointer is not null.
There is an implicit conversion from the literal 0 to nullptr .
It is always set a pointer to zero after invalidating it so that you know a pointer that's non-zero is valid" is an anti-pattern. What happens if you have two pointers to the same object? Setting one to zero won't be better and it does not affect the other.
It's not clear for me how can i do that in C++. In Objective-C I can check a object in this way
if (myValue != [NSNull null]) { … }
myValue is compared with a null object (returned by class method), so this works great , if object has a value, even nil, if statement will return true.
So question is how to test correctly for a null pointer value, i did this way
if (myValue != NULL)
{
qDebug() << "It is not null";
}
but it is not working.
In C++ there's really no concept of null value, only null pointers. You can't compare something that isn't a pointer to NULL.
A pointer in C++ essentially contains an address to some memory location where you object or data is stored. In this case, a "NULL Pointer" is just an empty memory address. This is represented as a zero value. So to check it, you would write something like this:
SomeClass *someClassPointer = // ... call some method to get pointer
// Check for null pointer
if (someClassPointer == 0)
{
// Pointer is null
}
This can be simplified by doing this:
if (someClassPointer)
{
// For checking that the pointer is not null
}
if (!someClassPointer)
{
// For checking that a pointer is null
}
Short answer: it depends.
Longer answer: First of all you can not compare a reference (if the type of myValue is something like T&) nor stack allocated objects (if myValue is just T) for null - these types are always allocated and not null (unless you screw up your stack or do other bad stuff - but you won't check for these cases, because than you will have bigger problems).
The only types you can check for null are pointers (myValue is something of type T*). For those types:
if you use C++98, you can check against 0. NULL is usually just a macro (#define NULL 0).
if you use the new C++11 there is a new nullptr keyword and you should check against this one.
Since 0 evaluates to false and anything else to true, you can also just use the pointer like a normal bool. A nullptr is of type nullptr_t and has operator bool() implemented - so you also can this one like you would use a bool.
In general: in C++98 the lack of nullptr is a source of errors, so if you can use C++11, ALWAYS use nullptr - never use NULL or 0 (int is just the wrong type to assign to a pointer or to compare with a pointer - if you have overladed methods you will run into problems since the compiler would use a method with an int parameter instead of a pointer type if it is suitable).
Let's assume you have two functions:
void foo(int a);
void foo(void *);
If you now call
foo(NULL);
the first function will get called (what probably is not what you want. So in C++11 you would write:
foo(nullptr);
while in C++98 you would have to write:
foo((void *)0);
This is one reason why the lack of null is/was a big issue before C++98. If you want to have something similar than in Objective-C, you could write the following function (for C++98):
template<typename T>
inline bool isNull(const T *obj) {
return obj == ((const T *) 0);
}
// to use it:
if (isNull(myType)) { //myType is a pointer to something
// some code
}
Although I never saw that one used in practice.
I hope this answer helps in understanding the concept in C++.
If i'm right, you want to check for null pointers. This is actually very easy in C++
Foo *pInstanc = new Foo;
if(pInstance)
{
//do something with pInstance
}
Can you give me an example when I can't pass argument by reference and I need to use pointer. I've found an example, but I'm not sure.
Suppose you have a class D derived from the base class B. You need pointer if you want do so:
void function(B* b){...}
int main{
D* d;
function(d);
}
The single time where you can not use a reference and must use a pointer is if you allow the concept of "no argument" by passing a null pointer.
However, you might want to use pointers as arguments when you are actually storing a pointer to whatever was passed. Most C++ developpers will notice that you aren't using a reference and pay special attention to what your documentation says.
If there is a coding guideline (like Google's) that says to use pointer arguments, then that's what you do.
Otherwise, only declare your own function with pointer formal argument when
a nullpointer is a valid & meaningful actual argument, or
the actual argument is most naturally pointer already, or
you're going to store that pointer somewhere.
Possibly more cases, but I think you get the drift: when you have a choice (no coding guideline saying otherwise), prefer references.
Cheers & hth.,
Another case: if the thing you're passing is the last argument before varargs:
void fn1(A &a, ...); // Uh oh
void fn2(A *a, ...); // Good
I don't know if this is required by the standard, or is just a bug in the implementation of the C++ compiler I use.
Typically, you use pointers for one of two things:
Reassignability - you can't rebind a
reference.
Null pointers - there's no such
thing as a null reference.
If your intended use case does not need either of those two properties, use a reference. Else, use a pointer.
If you want to allow the lack of an object, you need to use pointers:
// This allows DoSomething to receive pointers to NULL, which cannot
// be done with references
void DoSomething(Something *pSomething)
{
if (pSomething)
{
...
}
}
int main()
{
Something *pSomething=NULL;
DoSomething(pSomething);
}
http://www.daniweb.com/forums/thread216353.html
Singly linked lists example were pointers and pointer of pointers are used as function parameters.
the only reason is if you need to pass null. I.e you want to call the function saying 'I haven't got one of those'
I think that if you want to pass a function, you have to pass it by pointer. I don't see how you can pass the function by reference.
For example, take the following function:
#include <iostream>
#include "math.h"
void myfun (double value, size_t nofloops, double (*function)(double))
{
std::cout << value << std::endl;
for (size_t i=0;i<nofloops;++i)
{
value = function(value);
std::cout << value << std::endl;
}
std::cout << "------------------" << std::endl;
}
void main()
{
myfun(100,10,sin);
myfun(100,10,cos);
myfun(100,10,sqrt);
}
The function in this small utility executes the given function a number of times, taking the result as input in the next iteration. I can't see how you can pass the function by reference.