While the C++ standard does not explicitly forbid calling a member function on a null pointer, the result may be unexpected as the behavior is undefined, and therefore possibly compiler dependent. Consider
// Test_class.h #pragma once class Test_class; class Test_class { public: Test_class( std::string s ); void good(); void bad(); private: std::string str; };
// Test_class.cpp #include <iostream> #include "Test_class.h" Test_class::Test_class( std::string s ): str( s ) { // Empty constructor } void Test_class::good() { std::cout << "Hello!" << std::endl; } void Test_class::bad() { std::cout << "Hello, " << str << "!" << std::endl; }
If you compile this program with the GNU C++ compiler:
#include "Test_class.h" int main(); int main() { Test_class *p_jane{new Test_class( "Jane" )}; Test_class *p_bob{nullptr}; p_jane->good(); p_bob->good(); p_jane->bad(); p_bob->bad(); delete p_jane; return 0; }
If you were to compile this with the GNU C++ compiler, this would be the expected result:
Hello! Hello! HelloJane! Segmentation fault (core dumped)
We could try to protect ourselves by explicitly testing whether or not this == nullptr:
void Test_class::bad() { if ( this == nullptr ) { std::cout << "Hello?" << std::endl; } else { std::cout << "Hello, " << str << "!" << std::endl; } }
If you were to compile this, the current version of the GNU C++ compiler would print Hello? rather than causing a run-time segmentation fault.
Unfortunately, other compilers (for example, the one that comes with Visual Studio) will essentially ignore the test, for by definition, this should never equal nullptr, so the condition should never be true. This is an example of an optimization and it is no different than a compiler looking at
#include <iostream> int main(); int main() { if ( 3 == 4 ) { std::cout << "Good bye!" << std::endl; } else { std::cout << "Hello!" << std::endl; } return 0; }
and deciding that the consequent body of the conditional statement will never be executed, no matter what, so there is no point in compiling it. The GNU C++ compiler compiles both the previous and following programs into the exact same executable:
#include <iostream> int main(); int main() { std::cout << "Hello!" << std::endl; return 0; }Thus, the Visual Studio compiler will always cause a run-time termination of the program when Test_class::bad() is called on a null pointer.