Creating Smart pointer of the object itself (this) in its constructor - c++

So lets say I have
class A
{
A(std::vector<std::shared_pointer<A>> &a_vec)
{
auto shared_ptr = std::make_shared<A>(*this);
a_vec.pushback<shared_ptr>;
{
};
class B
{
std::vector<std::shared_pointer<A>> a_vector_;
void constructA()
{
created_A = make_shared<A>(a_vector_);
}
}
So Im creating a method for B which creates an A and the A pushes itself to the vector B provides.
And on paper this dependancy works like I expected to, atleast I thought it was until I realised the a_vec.pushback<this*>; is not very dependable.
When I have more code inbetween the push and the shared pointer initialisation as such
A(std::vector<std::shared_pointer<A>> a_vec)
{
auto shared_ptr = std::make_shared<A>(*this);
//insert more code here
a_vec.pushback<shared_ptr>;
{
It seems that the initialisations and other stuff I do in there isn't reflected to the pointer the shared pointer is pointing. Whats the cause of this and is there a way to fix it? Also is there a reason this would be a bad practice to use?

One of the challenges when you are programming in C++ is to understand object lifetime. So it is better to make object creation and destruction as clear as possible.
As I understood your case is to memoize "automagically" all created objects. It is easier to do using "factory method" constructA
#include <iostream>
#include <vector>
#include <memory>
class A
{
public:
A() = default;
};
class B//AInstanceFactory - is a better name
{
std::vector<std::shared_ptr<A>> a_instances;
public:
void constructA()
{
a_instances.push_back(std::make_shared<A>());
}
const std::vector<std::shared_ptr<A>>& getAInstances() {
return a_instances;
}
};
int main()
{
B b;
b.constructA();
std::cout << b.getAInstances().size() << "\n";
b.constructA();
std::cout << b.getAInstances().size() << "\n";
}
[WRONG PATH]
It is possible to make object which aware of shared_ptr/weak_ptr: use template std::enable_shared_from_this.
In that case your code might be following,:
#include <iostream>
#include <vector>
#include <memory>
class A : std::enable_shared_from_this<A>
{
public:
A(std::vector<std::shared_ptr<A>>& a_vec)
{
a_vec.push_back(shared_from_this());//bad_weak_ptr here!!!!
}
};
class B
{
std::vector<std::shared_ptr<A>> a_vector_;
public:
void constructA()
{
auto a_ptr = make_shared<A>(a_vector_);
}
const std::vector<std::shared_ptr<A>>& getAVec() {
return a_vector_;
}
};
int main()
{
B b;
b.constructA();
std::cout << b.getAVec().size() << "\n";
}
BUT it wrong, because underlying weak_ptr is "ready" only after function make_shared is executed, means only after construction call.
Calling shared_from_this or weak_from_this is valid only after make_shared function is executed.

Related

vector of call back functions and function pointer binding

I am new to the std::function and trying to implement a callback function. In the following code "Callback_t" contains a function that holds a vector of function to be called. Class "other" is a nested class inside "SomeClass". An object of "SomeClass" contains an array of nested class object "b". The "other" class constructor assigns a function pointer to "fptr". I push this function in to the vector of callback class "Callback_t". When I run this code, I get the segmentation fault when the first function in the vector is invoked. I am not able to figure out what is wrong with the statement
this->loc_ptr->set_of_cb.push_back(this->b[i].fptr);
However if I replace it with
this->loc_ptr->set_of_cb.push_back(std::bind(&other::func, &(this->b[i])))
the code works perfectly. I need help to understand what's wrong with the original statement.
#include <functional>
#include <iostream>
#include <vector>
typedef std::function<void(void)> func_type;
class Callback_t {
public:
std::vector<func_type> set_of_cb;
void myCallback()
{
for (int i = 0; i < set_of_cb.size(); i ++){
set_of_cb[i]();
}
}
};
class SomeClass;
class SomeClass {
private:
Callback_t *loc_ptr;
int a[10];
class other{
public:
int id;
SomeClass *loc;
func_type fptr;
other(){};
other(SomeClass *loc, int id){
this->id = id;
this->loc =loc;
fptr = std::bind(&other::func,this);
}
void func(void){
this->loc->a[id] = loc->a[id] * id;
return;
}
};
public:
other *b;
//other b[10];
SomeClass(Callback_t *a = nullptr){
this->loc_ptr = a;
this->b = new other[10];
for(int i =0; i <10;i++){
this->a[i] = i;
this->b[i] = other(this, i);
this->loc_ptr->set_of_cb.push_back(this->b[i].fptr);
}
}
void read(void){
for(int i =0; i <10;i++){
std::cout<<a[i]<<std::endl;
}
}
};
int main()
{
Callback_t *tmp;
tmp = new Callback_t;
SomeClass tmp1(tmp);
tmp1.read();
tmp->myCallback();
tmp1.read();
delete tmp;
}
other(SomeClass *loc, int id){
this->id = id;
this->loc =loc;
fptr = std::bind(&other::func,this);
}
The constructor binds fptr to this, which is the constructed object. Now, pay careful attention:
this->b[i] = other(this, i);
This performs the following sequence of events. There are quite a few things happening here, that are crucial to this mystery:
A temporary other object gets constructed, and its constructor does what it does. Note that the object is temporary, so its constructor ends up binding its fptr to a temporary object! You're beginning to see the problem, but let's close the loop, anyway:
The object gets assigned to this->b[i]. This is effectively a copy.
The original temporary objects gets destroyed.
The end result is that b[i]'s bound function ends up getting bound to a temporary object that is now destroyed. This results in undefined behavior and your crash.
And with your working alternative:
this->loc_ptr->set_of_cb.push_back(std::bind(&other::func, &(this->b[i])))
You are binding the std::function to a valid instance of the object, in b[i].
That's it.
The other answer explains what is going wrong in your code. What is left to do is to show case a more canonical example of achieving what you go for (with a little help from lambda functions). Of course, std::bind() also works, but it is pre C++11 and I think nowadays most would rather do it as I do in my code below.
#include <iostream>
#include <functional>
#include <vector>
class Foo {
public:
void FooFun() {
std::cout << "Foo::FooFun() called" << std::endl;
}
};
class Bar {
public:
void BarFun() {
std::cout << "Bar::BarFun() called" << std::endl;
}
};
using CallbackFun_t = std::function<void()>;
using Callbacks_t = std::vector<CallbackFun_t>;
int main(int argc, const char * argv[]) {
Foo foo{};
Bar bar{};
Callbacks_t callbacks
{ [&foo]{ foo.FooFun();}
, [&bar]{ bar.BarFun();}
};
for( auto& cb : callbacks ) {
cb();
}
return 0;
}

Accessing object unique_ptr is pointing to

Really simple question:
I'm kinda new to smart pointers in C++. I think I got the ownership stuff, but I have no idea how to access what they're actually pointing to. When I try to use the member functions/variables of the object I just get the functions of the unique_ptr class, which is not what I want.
I can see three ways of doing that: operator->, operator*, get().
Here is a running code example: ideone it
#include <iostream>
#include <memory>
struct Foo
{
Foo(std::string v) : value(v) {}
void Bar() { std::cout << "Hello, " << value << "!" << std::endl; }
std::string value;
};
int main() {
std::unique_ptr<Foo> FooPtr = std::make_unique<Foo>("World");
FooPtr->Bar();
FooPtr.get()->Bar();
(*FooPtr).Bar();
return 0;
}

enable_shared_from_this Vs Direct Assignment

Why should I use enable_shared_from_this as I can get the same effect via plain assignment also.
struct A : std::enable_shared_from_this<A> {
std::shared_ptr<A> getptr() {
return shared_from_this();
}
};
int main () {
// What is the differentce between this code
std::shared_ptr<A> p1 = make_shared<A>();
std::shared_ptr<A> p2 = p1->getptr();
// Vs this
std::shared_ptr<A> p1 = make_shared<A>();
std::shared_ptr<A> p2 = p1;
}
Because you can't get the "same" effect", at least not the one you may be thinking of.
There is no difference in the posted code methodologies, precisely because A inherits from std::enable_shared_from_this<A>. Both p1 and p2 are shared_ptr objects referring to the same concrete object (assuming only one of those sections is compiled for your tests, else you error on id name reuse).
std::enable_shared_from_this<T> allows you to acquire a std::shared_ptr<T> from some object, formally managed by some preexisting std::shared_ptr<T> of type T or derivative thereof, in locations where you have no std::shared_ptr<T> to the object to otherwise acquire, but need one for one reason or another. For example:
#include <iostream>
#include <memory>
struct A;
void foo(std::shared_ptr<A> arg)
{
}
struct A : std::enable_shared_from_this<A>
{
void method()
{
foo(shared_from_this());
}
};
int main ()
{
auto a = std::make_shared<A>();
a->method();
}
In the above example, foo requires a std::shared_ptr<A> as a parameter. From the body of A::method() no such mechanism exists without std::enable_shared_from_this<A> as a base. Without the std::enabled_shared_from_this<T> base, you would have to provide an alternative mechanism for passing the a shared pointer down the call chain until it reached foo. In short it would look something like this:
#include <iostream>
#include <memory>
struct A;
void foo(std::shared_ptr<A> arg)
{
}
struct A
{
void method(std::shared_ptr<A> me)
{
foo(me);
}
};
int main ()
{
std::shared_ptr<A> a = std::make_shared<A>();
a->method(a);
}
which is obviously dreadful and hideous. Further, there is no guarantee me in method is actually a std::shared_ptr<T> of this. Thus the standards committee blessed us with std::enable_shared_from_this<T>.
It's probably worth mentioning what shared_from_this is 'for'.
The most common use case is to 'keep myself alive' while some asynchronous process is running. A good example of this would be a completion handler, another would be a callback on 'this' when this is controlled by a shared_ptr.
for example:
#include <memory>
#include <future>
#include <thread>
#include <chrono>
#include <iostream>
using namespace std::literals;
template<class Handler>
void long_process_with_completion_handler(Handler done)
{
std::thread([done] {
std::cout << "long process starts" << std::endl;
std::this_thread::sleep_for(2000ms);
done();
}).detach();
}
struct controller : std::enable_shared_from_this<controller>
{
auto get_lock() const {
return std::unique_lock<std::mutex>(_mutex);
}
void start() {
long_process_with_completion_handler([self = shared_from_this()] {
auto lock = self->get_lock();
std::cout << "all complete" << std::endl;
});
}
mutable std::mutex _mutex;
};
int main()
{
std::condition_variable controller_done;
std::mutex done_mutex;
bool is_controller_done = 0;
// make shared controller
// start its processing
auto pcontroller = std::shared_ptr<controller>{ new controller,
[&](auto*p) {
delete p;
auto lock = std::unique_lock<std::mutex>(done_mutex);
is_controller_done = true;
std::cout << "controller destroyed" << std::endl;
lock.unlock();
controller_done.notify_all();
}};
pcontroller->start();
// destroy the controlling pointer. but our controller is still running...
pcontroller.reset();
auto lock = std::unique_lock<std::mutex>(done_mutex);
controller_done.wait(lock, [&]{ return is_controller_done;});
std::cout << "program ends" << std::endl;
}
The shared-from-this functionality enables you to obtain a shared_ptr to a shared_ptr-managed object when all you have is a raw pointer or a reference.
Just creating a shared_ptr directly from the raw pointer would create a new, unrelated reference counter.
The use case of enable_shared_from_this and shared_from_this is clear, and yet I tend to say that in most use cases it can be dropped in favor of a static method that gets a shared_ptr and then creates a new shared_ptr from it (in a very similar manner to the approach suggested by the OP, but with a static method to support the creation of the new shared_ptr).
The advantage of the static method approach is that you won't fall in the bug of trying to get shared_from_this when there is no underlying shared_ptr for this instance, resulting with bad_weak_ptr.
The disadvantage is that the API is implicitly asking the caller to come with a shared_ptr, so if the caller has just a raw pointer to an instance he can't use it (the caller may create a shared_ptr from the raw pointer and call the method, but how can he tell if the original raw pointer was not managed already by a shared_ptr?). On the other hand, if the user has in hand a unique_ptr he should be positively sure that turning it to shared_ptr in order to call the static method should be fine.
In a way the advantage and disadvantage are two sides of the same coin.
I would prefer in most cases to require the API to work with shared_ptr (it already depends on that in a way) rather than allowing working with any kind of a pointer, with the hope that there is a managed shared_ptr for it. This goes well with the advice of having APIs that cannot be easily used in a wrong way.
Here is the code presented by #RichardHodges (great example!) using the static method approach instead of using enable_shared_from_this:
// code based on Richard Hodges example
template<class Handler>
void long_process_with_completion_handler(Handler done) {
std::thread([done] {
std::cout << "long process starts" << std::endl;
std::this_thread::sleep_for(2000ms);
done();
}).detach();
}
// without the need to inherit from std::enable_shared_from_this
struct Controller {
auto get_lock() const {
return std::unique_lock<std::mutex>(_mutex);
}
static void start(std::shared_ptr<Controller>& pcontroller) {
long_process_with_completion_handler(
[self = std::shared_ptr<Controller>(pcontroller)] {
auto lock = self->get_lock();
std::cout << "all complete" << std::endl;
});
}
mutable std::mutex _mutex;
};
int main() {
std::condition_variable controller_done;
std::mutex done_mutex;
bool is_controller_done = 0;
// make shared controller and start its processing
auto pcontroller = std::shared_ptr<Controller>{ new Controller,
[&](auto*p) {
delete p;
auto lock = std::unique_lock<std::mutex>(done_mutex);
is_controller_done = true;
std::cout << "controller destroyed" << std::endl;
lock.unlock();
controller_done.notify_all();
}};
Controller::start(pcontroller);
// destroy the controlling pointer. but our controller is still running...
pcontroller.reset();
auto lock = std::unique_lock<std::mutex>(done_mutex);
controller_done.wait(lock, [&]{ return is_controller_done;});
std::cout << "program ends" << std::endl;
}
Code: http://coliru.stacked-crooked.com/a/281b0ef6d1b31c56

Calling a virtual function on a vector of base classes

I created some code to reproduce the problem:
#include "stdafx.h"
#include <iostream>
#include <vector>
class A
{
protected:
int m_X;
public:
A() {
std::cout << "in A ctor" << std::endl;
m_X = 0;
}
virtual void printX(){ std::cout << "in A " << m_X << std::endl; }
};
class B : public A
{
public:
B() {
std::cout << "in B ctor" << std::endl;
m_X = 1;
}
virtual void printX(){ std::cout << "in B " << m_X << std::endl; }
};
class As
{
public:
void AddA( const A &a ){ m_As.push_back( a ); }
void PrintXs()
{
for ( auto a : m_As )
{
a.printX();
}
}
private:
std::vector<A> m_As;
};
int _tmain(int argc, _TCHAR* argv[])
{
As as;
B b;
as.AddA( b );
as.PrintXs();
system("pause");
return 0;
}
The output of this is:
in A ctor
in B ctor
in A 1
I want "in B 1" instead of "in A 1". I'm sure my understanding of virtual is flawed. How must I change the code to call the B PrintX()? Note that there will be other classes that inherit from A so I really don't want to code a static call.
Thanks.
What you're doing is called slicing. This is where you take an object of a derived class and trim off everything that is not in the parent and assign it to the parent.
What you want to do is use polymorphism to do what you explained. To do this, change your vector from a copy of the object, to a ptr to the object.
If interested in more details, please use the links provided, the information included in them seems to be very complete.
The quick fix is to change your As class to the following:
class As
{
public:
void AddA( A &a ){ m_As.push_back( &a ); }
void PrintXs()
{
for ( auto a : m_As )
{
a->printX();
}
}
private:
std::vector<A*> m_As;
};
When you use std::vector<A> m_As;, the vector can only fit A objects. If you use pointers instead then polymorphism can work and call the correct printX function. However, this has the problem of dangling pointer if the lifetime of the pointed to object expires. To handle that it would be better to use a smart pointer class like std::unique_ptr.
Since you're passing objects by value you can not take advantages of polymorphism. Pass them by (smart) pointers or references.
std::vector<std::shared_ptr<A>> m_As;
// or
std::vector<std::unique_ptr<A>> m_As;
// or
std::vector<A*> m_As; // be careful of bare pointers
// or (since C++11)
std::vector<std::reference_wrapper<A>> m_As;
std::reference_wrapper magic!
For the last one, you can use std::reference_wrapper and std::ref:
class As
{
public:
void AddA(A &a){ m_As.push_back( std::ref(a) ); }
void PrintXs() const
{
for ( auto a : m_As )
{
a.get().printX();
}
}
private:
std::vector<std::reference_wrapper<A>> m_As;
};
Using last code, you don't have to change main code.
Live code
for ( const auto & a : m_As )
{
a.printX();
}
it will keep you from expanded copy and provide the B-instance instead of A-instance, appeared as copy.

Why aren't these shared_ptrs pointing to the same container?

I have a class Model:
class Model
{
...
boost::shared_ptr<Deck> _deck;
boost::shared_ptr<CardStack> _stack[22];
};
Deck inherits from CardStack.
I tried to make _stack[0] point to the same thing that _deck points to by going:
{
_deck = boost::shared_ptr<Deck>(new Deck());
_stack[0] = _deck;
}
It seems that the assignment to _deck of _stack[0] results in a copy of _deck being made. (I know this because modifications to _stack[0] do not result in modifications to _deck.) How can I get them to point to the same thing?
Ok - no copy constructor is being called. I have verified this by implementing it and seeing if it gets called - it doesn't.
However - I have a function that operates on CardStack objects:
void TransferSingleCard(CardStack & src, CardStack & dst, Face f)
{
if( !src._cards.empty() )
{
src._cards.back().SetFace(f);
dst.PushCard(src._cards.back());
src._cards.pop_back();
}
}
Now - when I call:
{
TransferSingleCard(*_stack[DECK], _someotherplace, FACEDOWN);
std::cout << *_stack[DECK];
std::cout << *_deck;
}
I get this output (where std::cout on a CardStack will print out the size of that stack):
Num(103) TOP
Num(104) TOP
... so I've concluded (incorrectly?) that _stack[DECK] points to something different.
The Deck
class Deck : public CardStack
{
public:
Deck(int numsuits=2, StackIndex index = NO_SUCH_STACK );
Deck::Deck( const Deck & d);
int DealsLeft() const;
void RecalcDealsLeft();
private:
int _dealsleft;
};
Not clear what you are asking about - consider this code:
#include <iostream>
#include "boost/shared_ptr.hpp"
using namespace std;
struct A {
virtual ~A() {
cout << "destroyed" << endl;
}
};
struct B : public A {
};
int main() {
boost::shared_ptr<B> b( new B );
boost::shared_ptr<A> a;
a = b;
}
Only one "destroy" message appears, indicating that no copy has been made.
This example - derives from #Neil's answer, tries to emulate what you say is happening. Could you check that it works as expected (A and B have the same count) on your system.
Then we could try and modify this code or your code until they match.
#include <boost/shared_ptr.hpp>
#include <iostream>
class A {
public:
virtual ~A()
{
std::cerr << "Delete A" << std::endl;
}
int _count;
void decrement()
{
_count --;
}
};
class B : public A {
public:
virtual ~B()
{
std::cerr << "Delete B" << std::endl;
}
};
int main()
{
boost::shared_ptr<B> b(new B);
b->_count = 104;
boost::shared_ptr<A> a;
a = b;
a->decrement();
std::cerr << "A:" << a->_count << std::endl;
std::cerr << "B:" << b->_count << std::endl;
return 0;
}
EDIT:
So from the comment, we know the original pointers are correct, so now we need to trace.
Either:
log pointers to see when they change.
Use watchpoints in a debugger to see when the pointer changes.
Use a third shared pointer to see which pointer is changed.
Introduce a function that changes both pointers at the same time.
I think the problem is that you're assigning between different types here. boost::shared_ptr is a template and templates are not polymorphic even if the type in them is. So what's happening is that your compiler sees the assignment from boost::shared_ptr<Deck> to boost::shared_ptr<CardStack> and notices that it can make the assignment by calling the copy constructor for CardStack to duplicate the Deck object.
I think what you want the assignment to look like is something like this:
_stack[0] = boost::static_pointer_cast<CardStack>(_deck);
Which will do the conversion the way you expect it to.
I think you may want shared_array for _stack . . . Take a look at the documentation on shared_ptr;from boost.org, specifically:
http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/shared_ptr.htm
"Normally, a shared_ptr cannot
correctly hold a pointer to a
dynamically allocated array. See
shared_array for that usage."
Also, be aware of the T* get() function (not to be used without good reason) which returns the raw pointer being held by the managed pointer (shared_ptr in this case).