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.
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()
I'm trying to pass a variable number of objects by reference in C++11.
The C-style of variadic argumnets did not seem very elegant, so I tried using the std::initialiszer_list.
But all the examples i found used pass by copy, I wrote a simple example of what I want to achieve:
//Example class for illustration purposes
class MyClass
{
public:
MyClass()
: m_id(0), m_idChecks(0)
{}
~MyClass(){}
int getId()
{
m_idChecks++;
return m_id;
}
int getIdChecks() const
{
return m_idChecks;
}
private:
int m_id;
int m_idChecks;
};
// I want to do something like this (pass the objects by reference):
// void test_initializerList(std::initializer_list<MyClass&> listClasses)
// But only pass by copy works:
void test_initializerList(std::initializer_list<MyClass> listClasses)
{
// Doing operations on copies of the object:
int sum = 0;
for(auto c : listClasses)
{
sum += c.getId();
}
std::cout << "\n id: " << sum;
}
void test()
{
MyClass c1;
MyClass c2;
MyClass c3;
test_initializerList({c1,c2,c3});
std::cout << "\n Wanted: " << 1 << " id checks, got: " << c1.getIdChecks() << "\n";
}
So how do you pass a variable number of arguments in modern C++? Examples are appreciated!
Unfortunately, initializer_list can only copy it's arguments, and can't hold a reference to it (directly at least). However, there is way around it (example trimmed):
#include <initializer_list>
#include <iostream>
#include <functional>
//Example class for illustration purposes
class MyClass
{
public:
MyClass() : m_idChecks(0) {}
~MyClass(){}
int getId() const
{
return m_idChecks++;
}
int getIdChecks() const
{
return m_idChecks;
}
private:
mutable int m_idChecks;
};
using r = std::reference_wrapper<MyClass>;
void test_initializerList(std::initializer_list<r> listClasses)
{
// Doing operations on copies of the object:
int sum = 0;
for(const auto& c : listClasses)
{
sum += c.get().getId();
}
}
int main()
{
MyClass c1;
MyClass c2;
MyClass c3;
test_initializerList({c1,c2,c3});
std::cout << "\n Wanted: " << 1 << " id checks, got: " << c1.getIdChecks() << "\n";
}
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.
It's hard to explain exactly what I want to do here, but I have a base class and two classes which inherit this base class. Both classes which inherit it have their own unique members. I want to be able to pass both to a method, and have that method detect which it is, then access their unique members. I can't assume there will only be two classes which inherit it, so i'm looking for something of a more general solution.
Here is an example of what I'd like to do:
#include <iostream>
class Base {
public:
int _type;
Base() { }
};
class First : public Base {
public:
int _first_only;
First() { }
};
class Second : public Base {
public:
int _second_only;
Second() { }
};
void test (Base b) {
std::cout << "Type: " << b._type << std::endl;
if(b._type==1) {
std::cout << "First\n";
// Want to be able to do this
std::cout << "Val: " << (First)b._first_only << std::endl;
} else if(b._type==2) {
std::cout << "Second\n";
// And this
std::cout << "Val: " << (Second)b._second_only << std::endl;
}
}
int main() {
First f;
f._first_only=1;
f._type=1;
Second s;
s._type=2;
s._second_only=2;
test(f);
test(s);
}
This is similar to others answers:
You can write polymorphic classes to get this behavior using virtual functions.
Pass the Dervied class objects either by pointer or by reference to get polymorphic behaviour. Otherwise it will lead to object slicing. Your test() function leads to object slicing.
This code may also help you. You can see that there are different ways to print the type. I used GetBaseType(), GetDerivedType() and GetType(). Among these GetType() method is convenient for you case. There are two constructors for convenience. Constructors allow to initialize data members.
class Base {
private:
int _type;
public:
Base(int type) : _type(type) { }
int GetBaseType() { return _type; }
virtual int GetDerivedType() = 0;
virtual int GetType() { return _type; }
};
class First : public Base {
private:
int _first_only;
public:
First() : Base(1), _first_only(1) { }
First(int first_only) : Base(first_only), _first_only(first_only) { }
int GetDerivedType() { return _first_only; }
virtual int GetType() { return _first_only; }
};
class Second : public Base {
private:
int _second_only;
public:
Second() : Base(2), _second_only(2) { }
Second(int second_only) : Base(second_only), _second_only(second_only) { }
int GetDerivedType() { return _second_only; }
virtual int GetType() { return _second_only; }
};
void test (Base &b) {
std::cout << "Type: " << b.GetBaseType() << std::endl;
std::cout << "Type: " << b.Base::GetType() << std::endl;
std::cout << "Dervied type: \n";
std::cout << "Val: " << b.GetDerivedType() << std::endl;
std::cout << "Val: " << b.GetType() << std::endl;
}
int main() {
First f(1);
Second s(2);
test(f);
test(s);
First f1;
Second s1;
test(f1);
test(s1);
}
Either declare a virtual function in Base
Move the common members types from First and Second into Base.
For your specific problem, 2nd option is better:
class Base {
public:
int _member; // have getter() method, if '_member' is private
Base() { }
};
Inside, test():
void test (Base &b) { // <--- practice to pass by reference if copy is not needed
// use b._member;
};
Your code does not work polymorphically, because you are passing the function-parameter by value, which results in slicing.
If you have a method that does different things for different types, consider overloading it for each of these types.
Three things I'd do:
In general switching on type codes is not considered good object oriented design: Instead pull the switched code into the classes.
I'd also set up the type tags in the constructor of the specific classes.
And as others have mentioned you need to pass the argument by reference to avoid slicing.
Here's what the code would look like:
#include <iostream>
class Base {
public:
int _type;
Base() { }
virtual void print_to_stream( std::ostream & os ) const =0;
};
class First : public Base {
public:
int _first_only;
First() { _type =1; }
void print_to_stream( std::ostream & os ) const
{
os<<"First\n";
os<<"Val: " << _first_only << std::endl;
}
};
class Second : public Base {
public:
int _second_only;
Second() { _type=2; }
void print_to_stream( std::ostream & os ) const
{
os << "Second\n";
os << "Val: " << _second_only << std::endl;
}
};
void test (Base & b)
{
std::cout << "Type: " << b._type << std::endl;
b.print_to_stream( std::cout );
}
int main() {
First f;
f._first_only=1;
Second s;
s._second_only=2;
test(f);
test(s);
}
I have an existing application in C++ with a custom ArrayBase class that manages storage and access to a contiguously allocated region of memory. I have a separate ItrBase class that is used to access data in that ArrayBase. ArrayBase has a createItr() function that currently returns an ItrBase object.
I need to extend ArrayBase to use multiple memory allocations instead of one contiguous one. I have created an EnhancedArray class to do that. For this EnhancedArray to be compatible with the existing application, it's createItr() function must return something that works with the new multiple memory allocations.
So, I have created a derived EnhanceItr class to do this.
My problem is I can't figure out a way for hundreds of code occurrences like this:
ItrBase anIterator = anArray.createItr();
...
double x = anIterator.getData();
to use the EhancedItr's getData() function when anArray is an EnhancedArray.
Here is a simple application illustrating my basic arrangement.
#include <iostream>
using namespace std;
class ItrBase {
public:
ItrBase() { cout << "ItrBase constructor.\n"; };
~ItrBase() { cout << "ItrBase destructor.\n"; };
virtual int vfunc() {return 1;};
};
class EnhancedItr : public ItrBase {
public:
EnhancedItr() { cout << "EnhancedItr constructor.\n"; };
~EnhancedItr() { cout << "EnhancedItr destructor.\n"; };
int vfunc() {return 0;};
};
class ArrayBase {
public:
ArrayBase() { cout << "ArrayBase constructor.\n"; };
~ArrayBase() { cout << "ArrayBase destructor.\n"; };
virtual ItrBase & createItr() {cout << "in AB's createItr()\n"; return *new ItrBase(); };
};
class EnhancedArray : public ArrayBase {
public:
EnhancedArray() { cout << "EnhancedArray constructor.\n"; };
~EnhancedArray() { cout << "EnhancedArray destructor.\n"; };
EnhancedItr & createItr() {cout << "in EA's createItr()\n"; return *new EnhancedItr(); };
};
int main()
{
ArrayBase ab;
EnhancedArray ea;
ItrBase itr = ab.createItr();
ItrBase eitr = ea.createItr(); //EnhancedItr assigned to ItrBase
cout << "ArrayBase's Itr .vfunc(): " << itr.vfunc() <<std::endl;
cout << "EnhancedArray's Itr .vfunc(): " << eitr.vfunc() <<std::endl;
return 0;
}
Both calls to vfunc() above return 1, when I want the second call to return 0.
In main(), I know that if I change the ItrBase types to ItrBase &'s, I do get the desired return types, but then I am modifying my 'existing' code in hundreds of areas, and the destructors for the Iterators are not called.
Is there another strategy that I am not seeing?
Thanks.
Sure, if you're allowed to rewrite ItrBase, then you can use delegation to pass all function calls through to an implementation class, which you hold by pointer or reference so that polymorphism is in effect. This would look a lot like pimpl. And the callers would not have to be written at all, only recompiled.
EDIT: code for those not familiar with pimpl.
struct ItrBase
{
struct ItrImpl
{
virtual ~ItrImpl(){}
virtual int vfunc() = 0;
};
ItrBase(ItrImpl peer) : m_peer(peer) { cout << "ItrBase constructor.\n"; }
~ItrBase() { cout << "ItrBase destructor.\n"; }
int vfunc() { return m_peer->vfunc(); }
private:
const unique_ptr<ItrImpl> m_peer;
};
class ArrayBase
{
struct ItrImpl : public ItrBase::ItrImpl
{
virtual int vfunc() { return 0; }
};
public:
ArrayBase() { cout << "ArrayBase constructor.\n"; };
~ArrayBase() { cout << "ArrayBase destructor.\n"; };
virtual ItrBase createItr() { cout << "in AB's createItr()\n"; return ItrBase(new ItrImpl); };
};
class EnhancedArray : public ArrayBase
{
struct ItrImpl : public ItrBase::ItrImpl
{
virtual int vfunc() { return 1; }
};
public:
EnhancedArray() { cout << "EnhancedArray constructor.\n"; };
~EnhancedArray() { cout << "EnhancedArray destructor.\n"; };
virtual ItrBase createItr() { cout << "in EA's createItr()\n"; return ItrBase(new ItrImpl); };
};
You're running into a problem called slicing: createItr returns a reference, and then you're copying that into an ItrBase by-value. It's as if you did something like this:
EnhancedItr itr1 = ...;
BaseItr itr2 = itr1; // copy by-value
cout << itr2.vfunc(); // prints 1, not 0
You're also leaking memory: createItr returns a newly allocated object, but you're never deleting it. This is very bad, especially since you'd expect array iterators to be used frequently.
completely different thing you can do is use,
BOOST_AUTO(iterator, array);
and let compiler figure out return type.
BOOST_AUTO
Not being up-to-date with the Standard Library, I could not use the unique_ptr<> implementation suggested by Ben Voigt. (version >=4.3) I believe I have taken his concept and implemented it with basic pointers instead. Noting, however, that this implementation is not exception-safe. ItrImpl objects could be left undeleted.
Here's my code. Too bad createItr() has to return a ItrBase object rather than a pointer, otherwise I think I could have gotten auto_ptr<> to work. Output during program execution shows that ~ItrBase() is called only once for each instance, but I am suprised it is not called also during the object return from createItr(). Return value optimization?
#include <iostream>
using namespace std;
struct ItrBase
{
struct ItrImpl
{
virtual ~ItrImpl(){};
virtual int vfunc() const = 0;
};
ItrBase(ItrImpl* peer) : m_peer(peer) { cout << "ItrBase constructor.\n"; };
~ItrBase() { cout << "ItrBase destructor. \n"; delete m_peer; };
int getData() const { return m_peer->vfunc(); };
private:
ItrImpl* const m_peer;
};
class ArrayBase
{
struct ItrImpl : public ItrBase::ItrImpl
{
virtual int vfunc() const { return 0; };
};
public:
ArrayBase() { cout << "ArrayBase constructor.\n"; };
~ArrayBase() { cout << "ArrayBase destructor.\n"; };
virtual ItrBase createItr() { cout << "in AB's createItr()\n"; return ItrBase(new ItrImpl); };
};
class EnhancedArray : public ArrayBase
{
struct ItrImpl : public ItrBase::ItrImpl
{
virtual int vfunc() const { return 1; };
};
public:
EnhancedArray() { cout << "EnhancedArray constructor.\n"; };
~EnhancedArray() { cout << "EnhancedArray destructor.\n"; };
virtual ItrBase createItr() { cout << "in EA's createItr()\n"; return ItrBase(new ItrImpl); };
};
int main()
{
ArrayBase ab;
EnhancedArray ea;
ItrBase itr = ab.createItr();
ItrBase eitr = ea.createItr(); //EnhancedItr assigned to ItrBase
cout << "ArrayBase's Itr .vfunc(): " << itr.getData() <<std::endl;
cout << "EnhancedArray's Itr .vfunc(): " << eitr.getData() <<std::endl;
return 0;
}