In C++, can objects be null? - c++

Here's what I have done:
I've got a simple class:
class Person{
public:
Person();
}
And in my main:
int main() {
Person myPer = NULL;
}
This is impossible since C++ does not allow that, however:
int main() {
Person* perPtr = NULL;
Person myPer = *perPtr; // corrected, it was &perPtr(typo error) before answers
}
This compiles fine and as I see I did able to have a NULL object. So isn't it violating the rule that only pointers can be null in C++? Or is there such a rule in C++?
2nd one is after I wrote this code, I added a if statement checking whether myPer is NULL or not but that gave me error. So does it show that C++ does not really like the NULL object idea no matter what you do to make objects NULL...

Objects cannot be null, only pointers can. Your code is incorrect and does not compile, since its trying to initialize a Person from a pointer to a pointer to Person. If you were to change your code to
Person* perPtr = NULL;
Person myPer = *perPtr;
then it would be trying to initialize a Person out of a dereferenced null pointer to a Person, which is undefined behavior (and most likely a crash).
If you need to use the idioms where an object could be in a NULL state, you could use Boost.Optional:
boost::optional< Person > myPer = boost::none;
if( myPer )
{
myPer->do_something();
}
It's a generalization of what is usually done with pointers, except it does not use dynamic allocation.

This is undefined behaviour. C++ references cannot be legally set to NULL. If you want a "nullable reference", use a pointer.

This is called undefined behavior. Unexpected results may happen when you attempt to dereference NULL or get the address of NULL.

References are basically syntactically nicer way of saying pointers.

You can make a class that has "NULL" state.
E.g. a class that owns something else, such as a file handle or a window handle or anything else, such that it can be empty or not.
You can see this with any string class or with any container class.
if (x.empty()) ...
But the concept of "is null" is limited to pointers and smart pointers (or any class that you override to support such use cases.

You can not have a NULL object in C++. Your first attempt is trying to set an object equal to a pointer, and thus fails.
You can have a NULL pointer, and references are simply pointers with slightly different syntax.
You can de-reference a NULL pointer (as in the compiler will let you), but that's undefined behavior. If you're lucky, dereferencing NULL will crash, so you know what's going on.

I would not say the following is impossible since C++ does not allow it:
int main() {
Person myPer = NULL;
}
It is possible, and C++ does allow it. It all depends on how you've defined the classPerson. For example, if the class Person has a constructor as shown below:
class Person
{
public:
Person(char *) {}
};
then Person myPer = NULL will compile just fine : http://www.ideone.com/586Pf
Now how much useful such class can be is up to you. One may exploit the above fact, and may come up with cool and useful (utility) class.

Related

Avoiding null pointer crashes in C++ by overloading operators - bad practice?

I'm starting to write a rather large Qt application and instead of using raw pointers I want to use smart pointers, as well as Qt's own guarded pointer called QPointer.
With both standard library smart pointers and Qt's pointers the application crashes when a NULL pointer is dereferenced.
My idea was that I could add a custom overload to the dereference operators * and -> of these pointer types that check if the pointer is NULL.
Below is a short example that works fine so far. If a NULL pointer was dereferenced, a temporary dummy object would be created so that the application does not crash. How this dummy object would be processed might not be always correct, but at least there would be no crash and I could even react on this and show a warning or write it to a log file.
template <class T>
class Ptr : public std::shared_ptr<T> {
private:
T * m_temp;
public:
Ptr<T>(T * ptr) : std::shared_ptr<T>(ptr), m_temp(NULL) {}
~Ptr() {
if (m_temp) {
delete m_temp;
}
}
T * operator->() {
if (!std::shared_ptr<T>::get()) {
if (m_temp) {
delete m_temp;
}
m_temp = new T();
return m_temp;
} else {
return std::shared_ptr<T>::get();
}
}
T & operator*() {
return *operator->();
}
};
Of course I'll be doing NULL checks and try to eliminate the source of NULL pointers as much as possible, but for the rare case that it I forget a NULL check and the exception occurs, could this be a good way of handling it? Or is this a bad idea?
I would say this is a bad idea for a few reasons:
You cannot derive from standard library types. It may work until you change something benign in your code and then it breaks. There are various things you can do to make this more acceptable, but the easiest thing is to just not do this.
There are more ways to create a shared_ptr than just a constructor call. Duplicating the pointer value in your m_temp variable is likely just to lead things to be out of sync and cause more problems. By the time you cover all the bases, you will have probably re-implemented the whole shared_ptr class.
m_temp = new T(); seems like a frankly crazy thing to do if the old pointer is null. What about all the state stored in the object that was previously null? What about constructor parameters? Any initialization for the pointer? Sure, you could maybe handle all of these, but by that point you might as well handle the nullptr check elsewhere where things will be clearer.
You don't want to hide values being nullptr. If you have code using a pointer, it should care about the value of that pointer. If it is null and that is unexpected, then something further up the chain likely went wrong and you should be handling that appropriately (exceptions, error codes, logging, etc.). Silently allocating a new pointer will just hide the original source of the error. Whenever there is something wrong in a program, you want to stop or address the problem as close to the source as possible - it makes debugging the problem simpler.
A side note, if you are confident that your pointers are not null and don't want to have to deal with nullptr in a block of code, you may be able to use references instead. For example:
void fun1(MyObject* obj) {}
void fun2(MyObject& obj) {}
In fun1, the code might need to check for nullptr to be well written. In fun2, there is no need to check for nullptr because if someone converts a nullptr to a reference they have already broken the rules. fun2 pushes any responsibility for checking the pointer value higher up the stack. This can be good in some cases (just don't try and store the reference for later). Note that you can use operator * on a shared_ptr/unique_ptr to get a reference directly.

C++ member function requires pointer, bad practice to pass by reference?

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.

Segmentation Fault C++ casting issue

I am writting a parser, and when casting I am having trouble distingushing between a normal class type, and an array class type.
Having something similar to the following would help me a lot:
if (expression causes segmentation fault)
do sth
else
do sth else
If not this, then, what would be a good way to distinguish two classes from each other?
if (base->type->GetType() != "") {
char *key = strcpy(key, base->type->GetType().c_str());
Node *node = (stack->front).Lookup(key);
if (node != NULL) {
theclass = dynamic_cast<ClassDeclaration *>(node);
}
if (!base->GetType()->IsEquivalentTo(GetType()))
errReport.FieldNotFoundInBase(field, type);*/
if (theclass->id->name){ // segfault happens here.
The variable theclass, is sometimes initialized as an actual class, sometimes as an array. the seg faults happens in the line if (theclass->id->name) { when there is an array class instead of an actual class, since the array class doesn't really have a name field. I don't really have a way of telling in which type theclass variable is being initialized.
If node is an instance of ClassDeclaration, then dynamic_cast<ClassDeclaration *>(node) will return node "converted" to a ClassDeclaration* [1]. Otherwise, it returns 0 (or, more accurately, nullptr cast to ClassDeclaration*.
You don't check for the nullptr value. Dereferencing a nullptr will almost certainly segfault (although technically it's UB, so it could do anything.)
Now, it's possible that something more esoteric is going on and the segfault isn't happening because the dynamic_cast failed and returned nullptr and you then proceeded to dereference that value. It's possible. We'd all know for certain if you checked the return value.
Note 1: It's possible for dynamic_cast to change the pointer value, for example if the cast-to type is not the first base type of a multiply-inherited object. So I probably shouldn't have put scare-quotes around the word "converted".

return by reference or pointer and check for null?

I have a class :
class A
{
private:
vector<int> x;
public:
const vector<int>& immutable_data() {
return x;
}
vector<int>* mutable_data() {
return &x;
}
}
Now if i use this class , in my code , do i have to check if the pointer returned by the mutable_data() is null or not (given that i know the structure of this class). Personally i think i don't have to because i know there exist a secondary api which returns a const reference and so my pointer can never be null (I can't imagine of a scenario where this function would return me null ,even if it somehow does returns null, what would be the behavior of the const ref version in that case). Or should i say that i know its an address of an existing object on stack , so it cannot be null ? Is this the correct way to think or reason about this ? If any one thinks the other way , please give some example code.
For a more common case scenario in production code : if i use protocol buffers , i already know the generated code for my message templates (for eg: repeatedfields which are like stl containers), but do i still need to do null check every time i want to use the mutable api because they always return either by pointer or const reference.
returning by reference is not what i am looking for.
do i have to check if the pointer returned by the mutable_data() is null or not (given that i know the structure of this class)
In general, design elements like "have to check the pointer" depends on one of two things:
Does your design need to be provably safe?
If not, then does the design of A::mutable_data() dictate that it won't return null?
If (1), then you should invest in the kind of SAT-solver based tools which can test statically that your code won't access invalid memory.
If (2), I recommend that you consider the concept of Design by Contract -- it is a powerful one. If A::mutable_data()'s interface is specified not to return null, then it returning null would be a design defect in A::mutable_data().
Returning a null pointer usually means "I don't have any data for you". If the class will always have data, then, by design, the function will never return a null pointer. If that's the case, then code that uses the function does not need to check for null pointers. That's one of the guarantees that the function makes: "I won't ever return a null pointer".

Is it possible to set an object to null?

Further in my code, I check to see check if an object is null/empty.
Is there a way to set an object to null?
An object of a class cannot be set to NULL; however, you can set a pointer (which contains a memory address of an object) to NULL.
Example of what you can't do which you are asking:
Cat c;
c = NULL;//Compiling error
Example of what you can do:
Cat c;
//Set p to hold the memory address of the object c
Cat *p = &c;
//Set p to hold NULL
p = NULL;
While it is true that an object cannot be "empty/null" in C++, in C++17, we got std::optional to express that intent.
Example use:
std::optional<int> v1; // "empty" int
std::optional<int> v2(3); // Not empty, "contains a 3"
You can then check if the optional contains a value with
v1.has_value(); // false
or
if(v2) {
// You get here if v2 is not empty
}
A plain int (or any type), however, can never be "null" or "empty" in any useful sense. Think of std::optional as a container in this regard.
If you don't have a C++17 compliant compiler at hand, you can use boost.optional instead. Some pre-C++17 compilers also offer std::experimental::optional, which should behave at least close to the actual std::optional. Check your compiler's manual for details.
You can set any pointer to NULL, though NULL is simply defined as 0 in C++:
myObject *foo = NULL;
Also note that NULL is defined if you include standard headers, but is not built into the language itself. If NULL is undefined, you can use 0 instead, or include this:
#ifndef NULL
#define NULL 0
#endif
As an aside, if you really want to set an object, not a pointer, to NULL, you can read about the Null Object Pattern.
You want to check if an object is NULL/empty. Being NULL and empty are not the same. Like Justin and Brian have already mentioned, in C++ NULL is an assignment you'd typically associate with pointers. You can overload operator= perhaps, but think it through real well if you actually want to do this. Couple of other things:
In C++ NULL pointer is very different to pointer pointing to an 'empty' object.
Why not have a bool IsEmpty() method that returns true if an object's variables are reset to some default state? Guess that might bypass the NULL usage.
Having something like A* p = new A; ... p = NULL; is bad (no delete p) unless you can ensure your code will be garbage collected. If anything, this'd lead to memory leaks and with several such leaks there's good chance you'd have slow code.
You may want to do this class Null {}; Null _NULL; and then overload operator= and operator!= of other classes depending on your situation.
Perhaps you should post us some details about the context to help you better with option 4.
Arpan
"an object" of what type?
You can certainly assign NULL (and nullptr) to objects of pointer types, and it is implementation defined if you can assign NULL to objects of arithmetic types.
If you mean objects of some class type, the answer is NO (excepting classes that have operator= accepting pointer or arithmetic types)
"empty" is more plausible, as many types have both copy assignment and default construction (often implicitly). To see if an existing object is like a default constructed one, you will also need an appropriate bool operator==