The following code produces the output
outer::inner::inner, o=00000000
outer
outer::inner::val, o=00000000
outer::print
Can anyone explain how I can access the outer class method print through o without explicitly assigning o's value at construction?
Here o is null, but I can still invoke its methods.
I have tested this with MSVC 2017 and g++ 7.4.0 and the output is same.
#include <iostream>
class outer {
public:
outer() {
std::cout << __func__ << std::endl;
}
class inner {
outer *o = nullptr;
public:
inner() {
std::cout << __FUNCTION__ << ", o=" << o << std::endl;
}
void val() {
std::cout << __FUNCTION__ << ", o=" << o << std::endl;
o->print(); // **call outer class method**
}
};
inner i;
void print() {
std::cout << __FUNCTION__ << std::endl;
}
};
int main()
{
outer o;
o.i.val();
return 0;
}
You can simplify your example to
struct S
{
void f() { std::cout << "hello world\n"; }
};
int main()
{
S* s = nullptr;
s->f();
}
And dereferencing nullptr is UB. So anything can happen.
Why does it appear to work?
Because, in practice, method functions are generally implemented as if there were regular functions with extra parameter:
void S::f() -> void f(S*) (or void f(S&))
and so, code becomes:
void f(S* /*unused*/) { std::cout << "hello world\n"; }
int main()
{
S* unused = nullptr;
f(unused);
}
In that case, compiler transforms UB in valid code, as unused is not used, it doesn't crash and does what you expect.
Related
I am learning C++14, in that come across this template variable feature and that interested me to dig more on this and i tried with multiple examples to understand the template variables. Say,
template <typename T>
T var;
var<int>;
var<float>;
Above code worked and it looked straight forward to understand too. But, when I tried to use class name in place of int or float as shown above, result in calling the temporary object creation for the class FOO and calling corresponding C'tor & dtor for the temp object.
var<FOO>; //FOO is a class
I have written a sample test program and its output for your understanding. My question is that,
Why var creates temp object?
How template variable differ for primitive datatypes and user defined datatypes?
If it is irrelevant or duplicate, please point me to the source for clear understanding.
Refer code below,
class B
{
public:
B()
{
std::cout<<"\nB ctor"<<std::endl;
}
B(const B& obj)
{
std::cout<<"B copy ctor"<<std::endl;
}
int operator()()
{
std::cout<<"operator() called"<<std::endl;
}
void f() {
//::A().print();
}
~B()
{
std::cout<<"\n~ for B()"<<std::endl;
}
};
//Declaring template variable
template<typename T>
T g ;
int main() {
g<int> = 30;
g<float> = 30.02f;
g<B> = B{};
std::cout<<"g value:"<<g<int><<std::endl;
std::cout<<"g value:"<<g<float>;
}
Output:
B ctor
g value:30
g value:30.02
~ for B()
No temporary object is created by this simple program:
int main() {
var<SomeClass>;
}
A temporary object is created here:
int main() {
var<SomeClass> = SomeClass{};
}
but that is because we did it with SomeClass{}. We then assigned that to the var<SomeClass> non-temporary object (global in many of your examples).
The code that runs here is
SomeClass::SomeClass()
SomeClass::SomeClass()
SomeClass::operator=(SomeClass&&)
SomeClass::~SomeClass()
SomeClass::~SomeClass()
in that order.
#include <iostream>
struct noisy {
noisy() { std::cout << __func__ << "()\n"; }
~noisy() { std::cout << __func__ << "()\n"; }
noisy(noisy&&) { std::cout << __func__ << "(&&)\n"; }
noisy(noisy const&) { std::cout << __func__ << "(c&)\n"; }
void operator=(noisy&&) { std::cout << __func__ << "(&&)\n"; }
void operator=(noisy const&) { std::cout << __func__ << "(c&)\n"; }
};
template<class T>
T var;
int main() {
std::cout << "Start of main\n";
{
var<noisy> = noisy{};
std::cout << "Body of main\n";
}
std::cout << "End of main\n";
}
live example.
Output:
noisy()
Start of main
noisy()
operator=(&&)
~noisy()
Body of main
End of main
~noisy()
This question already has answers here:
const reference to a temporary object becomes broken after function scope (life time)
(2 answers)
Closed 4 years ago.
For regular local const reference variables, the scope is prolonged. Which is why the following code works as expected:
#include <iostream>
#include <memory>
struct foo
{
foo()
{
std::cout << "foo() #" << (void*)this << std::endl;
}
~foo()
{
std::cout << "~foo() #" << (void*)this << std::endl;
}
};
int main()
{
auto const& f = std::make_shared<foo>();
std::cout << "f = " << f.get() << std::endl;
return 0;
}
// prints:
// foo() #0x55f249c58e80
// f = 0x55f249c58e80
// ~foo() #0x55f249c58e80
It seems though that this does not work as expected when assigning a moved object using std::move():
#include <iostream>
#include <memory>
#include <list>
struct foo
{
foo()
{
std::cout << "foo() #" << (void*)this << std::endl;
}
~foo()
{
std::cout << "~foo() #" << (void*)this << std::endl;
}
};
int main()
{
std::list<std::shared_ptr<foo>> l;
l.push_back(std::make_shared<foo>());
auto const& f = std::move(l.front());
l.clear();
std::cout << "f = " << f.get() << std::endl;
return 0;
}
// prints
// foo() #0x564edb58fe80
// ~foo() #0x564edb58fe80
// f = 0x564edb58fe80
Does std::move() indeed change the scope, or am I dealing with a compiler bug?
Changing the variable from auto const& f to just auto f fixes the problem. If I wrap the move into another function, it also works:
auto const& f = [&]() { return std::move(l.front()); }();
It's almost like std::move() does not share the same semantics as a function call, but rather as if it was just a regular variable assignment:
auto const& f = std::move(l.front());
Let's put aside std::move() and create this function:
struct sometype {};
const sometype &foobar( const sometype &cref ) { return cref; }
and now we use it:
const sometype &ref = foobar( sometype() );
What do you think, will lifetime of temporary be prolongated in this case? No it would not. Lifetime is only prolongated when you assign to a reference directly. When it goes through a function or through static_cast or std::move that prolongation is gone. So you have exactly the same issue with std::move()
struct sometype {
sometype() { std::cout << "ctype()" << std::endl; }
~sometype() { std::cout << "~ctype()" << std::endl; }
};
const sometype &foobar( const sometype &cref ) { return cref; }
int main()
{
const sometype &cref1 = foobar( sometype() );
sometype &&cref2 = std::move( sometype() );
std::cout << "main continues" << std::endl;
}
output:
ctype()
~ctype()
ctype()
~ctype()
main continues
live example
Note: you should not use std::move() on return statement, it does not give you anything.
For your code change. You should remember that std::move() does not move anything. It is done by special assignment operator or constructor (if they provided for a type). So when you write this code:
const type &ref = std::move( something );
there is no constructor nor assignment operator involved and so no moving happens. For actual moving to happen you have to assign it to a variable:
type val = std::move( something );
now moving would happen if possible or copy otherwise.
Consider the following example:
struct B1 {
void f() {
this->g();
std::cout << this << std::endl;
}
void g() {
std::cout << "B1::g" << std::endl;
}
};
struct B2 {
void f() {
this->g();
std::cout << this << std::endl;
}
void g() {
std::cout << "B2::g" << std::endl;
}
};
struct C: B1, B2 {
void f() {
B1::f();
B2::f();
std::cout << this << std::endl;
}
void g() {
std::cout << "C::g" << std::endl;
}
};
int main() {
C c;
c.f();
return 0;
}
For me, the output is:
B1::g
0x7fffa11436b7
B2::g
0x7fffa11436b7
0x7fffa11436b7
Let us focus on B2::f. As seen from the output, inside B2::f, this points to the beginning of the object of type C. So, how is this->g() resolved correctly to B2::g()?
No functions are virtual here. So you you call g member function from B1::f you call by definition B1::g. Things would indeed go differently if g was virtual, because then all f functions would call C::g (just try to replace void g() with virtual void g() in all 3 structs)
I found a problem while using 3rd party code which cannot be altered. I need to make a copy of object member. I can't do this strictly because one of inner members has private assignment operator. The only solution I found is tricky so I want to ask you if you see any red lights that can affect my program.
Here's the simplified code I'm dealing with (remember that I cannot change it!):
#include <iostream>
#include <algorithm>
class MBool
{
public:
MBool() {};
MBool(const MBool& arg) {}
private:
MBool& operator=(const MBool& arg);
};
class InnerContent {
private:
int* pBuffer;
public:
InnerContent() {
pBuffer = new int[20];
std::cout << "InnerContent()" << std::endl;
}
InnerContent(const InnerContent& otherInnerContent) {
pBuffer = new int[20];
std::copy(otherInnerContent.pBuffer, otherInnerContent.pBuffer + 20, pBuffer);
std::cout << "InnerContent(const InnerContent&)" << std::endl;
}
~InnerContent() {
std::cout << "~InnerContent()" << std::endl;
delete [] pBuffer;
pBuffer = nullptr;
}
virtual void someVirtualFunction() {}
};
class Content {
public:
InnerContent innerContent;
int someNumber;
MBool boolVar;
Content() {
std::cout << "Content()" << std::endl;
}
~Content() {
std::cout << "~Content()" << std::endl;
}
Content(const Content& otherContent) :
innerContent(otherContent.innerContent),
someNumber(otherContent.someNumber),
boolVar(otherContent.boolVar)
{
std::cout << "Content(const Content&)" << std::endl;
}
virtual void someVirtualFunction() {}
};
class A {
public:
Content content;
A() { std::cout << "A()" << std::endl; }
~A() { std::cout << "~A()" << std::endl; }
};
class B {
public:
Content content;
B() { std::cout << "B()" << std::endl; }
~B() { std::cout << "~B()" << std::endl; }
};
And here's what I'm about to do with it (only this code can be modified and extended):
void copyContent(Content& contentFrom, Content& contentTo) {
contentTo.~Content();
new (&contentTo) Content(contentFrom);
};
int main() {
A a;
B b;
// I wish to do this:
//b.content = a.content;
// but Content class has no operator= function implemented
// also I can't use generated assignment operator function because of MBool::operator= is private
// The only work-around I found is this:
std::cout << "--- Before copying" << std::endl;
copyContent(a.content, b.content);
std::cout << "--- After copying" << std::endl;
}
My solution is to call Content destructor manually to free any dynamically allocated memory in Content and its inner classes. Memory on the stack remains untouched so I can reuse it with placement-new operator that calls copy constructor that is present and does exactly what I need. When main function scope ends 'a' object is cleaned up properly.
Code output:
InnerContent()
Content()
A()
InnerContent()
Content()
B()
--- Before copying
~Content()
~InnerContent()
InnerContent(const InnerContent&)
Content(const Content&)
--- After copying
~B()
~Content()
~InnerContent()
~A()
~Content()
~InnerContent()
I don't want to make my own function that copies all the fields because this class can be updated in new version and there may be additional field that I will not copy and most probably no one will remember to fix it.
Question: Do you think this may cause any memory leaks or memory corruption? Do you see any problems that I didn't mention?
Basically the Idea should work. To protect yourself from forgetting to call the destructor, I think, you should wrap the whole think in a kind of smart pointer like class template. In this example it actually does not wrap a pointer, but the content object itself.
template <typename ContentType>
class content_wrapper {
private:
ContentType content_;
public:
content_wrapper() : content_ {} {};
content_wrapper(const content_wrapper& other) :
content_{other.content_} {};
content_wrapper& operator = (const content_wrapper& other) {
content_.~ContentType();
new (&content_) ContentType(other);
return *this;
}
ContentWrapper& operator * () {
return content_;
}
ContentWrapper* operator -> () {
return &content_;
}
};
now you can use it like that:
class A {
public:
content_wrapper<Content> content;
A() { std::cout << "A()" << std::endl; }
~A() { std::cout << "~A()" << std::endl; }
};
class B {
public:
content_wrapper<Content> content;
B() { std::cout << "B()" << std::endl; }
~B() { std::cout << "~B()" << std::endl; }
};
int main() {
A a;
B b;
b.content = a.content; // the wrapper will take care.
b.content->someVirtualFunction();
}
Easy to read and you can never forget the destructor call, whenever you want to assign a content object.
Consider this code:
#include <iostream>
#include <functional>
using namespace std;
using namespace std::placeholders;
typedef function<void(const int&)> SomeFunc;
class X {
public:
X(string name):name_(name)
{ cout << "ctor " << name_ << endl; }
~X()
{
cout << "dtor " << name_ << endl;
name_ = "empty";
}
SomeFunc
getSomeFunc()
{ return bind(&X::someMethod, this, _1); }
private:
string name_;
void
someMethod(const int& a)
{
cout << name_ << " some method with " << a << endl;
}
};
int main()
{
SomeFunc f;
{
shared_ptr<X> x(new X("Object"));
f = x->getSomeFunc();
f(1);
}
f(2);
return 0;
}
Sometimes, output gives me this:
ctor Object
Object some method with 1
dtor Object
empty some method with 2
other times this:
ctor Object
Object some method with 1
dtor Object
some method with 2
In real world, it would most probably give me crashes once deallocated object tries to access it's attributes.
So here is a question - as function does not guarantee holding a reference to the object which method it's pointing to, what is the best practice to avoid crashes when function is called after referenced object was already deallocated?
One of the solutions I might think of - maintain a special flag bool deallocated_ inside object and check it inside the method which might be called after deallocation. However, I suspect, it's not reliable either.
UPDATE (from comments):
The real reason I need this workaround is the library that takes function as a parameter. This library operates asynchronously and I have no control over function objects passed into it. That's why when my object is deallocated, library still can invoke callbacks using originally passed function which leads to a crash.
Your object is being held by a shared_ptr, so you can use a lambda to close over the shared_ptr:
auto func = [ptr](const int &p){ ptr->someMethod(p); };
You'll need to use shared_from_this to get ptr within the class.
Here's a full example that works:
#include <iostream>
#include <functional>
#include <memory>
using namespace std;
using namespace std::placeholders;
typedef function<void(const int&)> SomeFunc;
class X : public enable_shared_from_this<X> {
public:
X(string name) : name_(name) {
cout << "ctor " << name_ << endl;
}
~X() {
cout << "dtor " << name_ << endl;
name_ = "empty";
}
SomeFunc getSomeFunc() {
auto ptr = shared_from_this();
return [ptr](const int &a){ ptr->someMethod(a); };
}
private:
string name_;
void someMethod(const int& a) {
cout << name_ << " some method with " << a << endl;
}
};
int main()
{
SomeFunc f;
{
shared_ptr<X> x(new X("Object"));
f = x->getSomeFunc();
f(1);
}
f(2);
return 0;
}
The output looks like this:
ctor Object
Object some method with 1
Object some method with 2
dtor Object
Sulution 1) Using weak_ptr + lambda (almost the same as from b4hand, but it won't force your class beeing alive)
Inherit your class from std::enable_shared_from_this
class X : public enable_shared_from_this<X>
and change getSomeFunc to something like this:
SomeFunc getSomeFunc()
{
weak_ptr<X> weak = shared_from_this();
return [weak, this](const int& a){
shared_ptr<X> shared = weak.lock();
if (shared)
{
this->someMethod(a);
}
};
}
output:
ctor Object
Object some method with 1
dtor Object
more details here and here.
Solution 2) A bit of crazy code + lambda
If you can't or don't want to use shared/weak ptrs, you can do it this way:
#include <memory>
#include <functional>
#include <iostream>
#include <memory>
#include <string>
#include <set>
using namespace std;
typedef function<void(const int&)> SomeFunc;
class X {
private:
static set<X*> _aliveInstanties;
public:
X(string name) :name_(name)
{
_aliveInstanties.insert(this);
cout << "ctor " << name_ << endl;
}
~X()
{
_aliveInstanties.erase(_aliveInstanties.find(this));
cout << "dtor " << name_ << endl;
name_ = "empty";
}
SomeFunc getSomeFunc()
{
return [this](const int& a)
{
if (_aliveInstanties.find(this) != _aliveInstanties.end())
{
this->someMethod(a);
}
};
}
private:
string name_;
void someMethod(const int& a)
{
cout << name_ << " some method with " << a << endl;
}
};
You can create a class that holds a function pointer and a shared_ptr to the object. The shared_ptr to the object guarantees the object won't be destroyed until your function class is destroyed.
Another solution without using lambda is to derive from enable_shared_from_this and pass shared_from_this in getSomeFunc method:
class X : public enable_shared_from_this<X> {
public:
X(string name):name_(name)
{ cout << "ctor " << name_ << endl; }
~X()
{
cout << "dtor " << name_ << endl;
name_ = "empty";
}
SomeFunc
getSomeFunc()
{
return bind(&X::someMethod, shared_from_this(), _1);
}
private:
string name_;
void
someMethod(const int& a)
{
cout << name_ << " some method with " << a << endl;
}
};
This, however, will hold object until all callbacks are released.