I have this test program:
#include <iostream>
#include <memory>
class A {
public:
A()
{
std::cout<<"A Constructor\n";
}
~A(){
std::cout<<"A Destructor\n";
}
void show()
{
std::cout<<"A::show()"<<'\n';
}
};
int main()
{
auto p1 = std::make_shared<A>();
// Relinquishes ownership of p1 on the object
// and pointer becomes NULL
p1.reset();
std::cout<<p1.get()<<'\n';
std::cout<<p1.use_count()<<'\n';
p1->show();
return 0;
}
Which yields this output:
A Constructor
A Destructor
0
0
A::show()
I ran this via gdb and saw:
:
:
(gdb) s
A::show (this=0x0) at so.cpp:18
18 std::cout<<"A::show()"<<'\n';
(gdb) s
A::show()
:
The line A::show (this=0x0) at so.cpp:18
indicates that the underlying resource is null. I looked at another question but there the raw pointer was being used to invoke the member function. Is this case too similar to the one in that question since p1->show()
too should be equivalent to something like p1.get()->show();
. Is my understanding correct?
Just add a data member to the class and you can see visually undefined behavior.
#include <iostream>
#include <memory>
class A {
public:
A()
{
std::cout<<"A Constructor\n";
}
~A(){
std::cout<<"A Destructor\n";
}
void show()
{
std::cout<<"A::show()"<<'\n';
++x;
}
int x = 0;
};
int main()
{
std::shared_ptr<A> p1(new A);
// Relinquishes ownership of p1 on the object
// and pointer becomes NULL
p1.reset();
std::cout<<p1.get()<<'\n';
std::cout<<p1.use_count()<<'\n';
p1->show();
return 0;
}
For example at run-time an error like this
Runtime error #stdin #stdout 0s 4280KB
can be shown.
That is the null-pointer was used to access the data member.