dereferenced unique_ptr and changing values in struct doesn't stick - c++

I'm trying to learn the basics of C++, and like everyone learning pointers is hard.
So, I'm trying out the C++14 std::unique_ptr class, and this is probably a silly question.
#include <iostream>
#include <memory>
struct Foobar {
bool active = false;
};
int main()
{
std::unique_ptr<Foobar> foobar = std::make_unique<Foobar>();
Foobar foo = *foobar;
foo.active = true;
Foobar bar = *foobar;
// prints zero and not one
std::cout << bar.active << std::endl;
}
Dereferencing my pointer and changing the bool in the struct doesn't change the actual underlying value in memory. Why is that so?
What basic thing am I missing?

Foobar foo = *foobar;
foo.active = true;
This makes a copy of the object referenced by foobar, and stores it in a new variable called foo; then modifies foo's active flag.
Of course, this does absolutely nothing to the original object that's (still) referenced by foobar.
The code then makes another copy of the object, and prints the unmodified value of its active flag.

Related

Convert std::thread pointed by void pointer to object std::thread instead of pointer to object

I was looking to an exercise I did, specifically a class "threads manager" which manage threads (omg really? lol) by storing them inside an array of "typedef void *HANDLE;" declared inside a struct GROUP.
So I already made it working, but I saw that I was converting the "HANDLE", so "void*", by "reinterpret_cast" conversion to "std::thread*".
After I saw that I worried: how and can I convert it directly to an std::thread object?
I did this code for example:
#include <iostream>
#include <thread>
typedef void *HANDLE;
class thread_obj {
public:
void operator()(int x){
for(int i = 0x0; i < x; i++){
std::cout << "i = " << i << std::endl;
}
}
};
int main(){
std::thread thr(thread_obj(), 0x3);
HANDLE test = &thr;
std::thread *p_thr = reinterpret_cast<std::thread*>(test);
p_thr->join();
return 0x0;
}
This is the original code.
If instead I do:
std::thread p_thr = reinterpret_cast<std::thread&>(test);
or:
std::thread p_thr = *reinterpret_cast<std::thread*>(test);
or:
std::thread *temp = reinterpret_cast<std::thread*>(test);
std::thread p_thr = *temp;
I always get:
error: use of deleted function ‘std::thread::thread(std::thread&)’
On "reinterpret_cast" line for the first and second case, and on the following assignment line for the third.
Now I suppose the problem is with the copy constructor called.
I searched a little and I opened the thread class and I found it:
thread(thread&) = delete;
So :/ searching a little I only found the solution on which you override the copy constructor.
In this case I think a solution could be make a superclass an re-declare this deleted constructor, right? But this is just a waste of time :/
So is there a way to convert this "void*" to "std::thread" object, again to a "std::thread" object?
If yes or no can you explain me in detail please?
Thank you so much
have a nice day and coding :D
What you really need is
std::thread& ref_thr = *reinterpret_cast<std::thread*>(test);
// ^ declare a reference to a std::thread
and then you can use ref_thr just like you would use a normal object.
As you've found, the copy constructor for std::thread is deleted, so if you actually want to create a thread object from test, then you need to move the casted object into new_thr like
std::thread new_thr = std::move(*reinterpret_cast<std::thread*>(test));
but this means that the object pointer to by test is no longer usable as it was moved into new_thr. This is why you want to use a reference, unless you actually want to move it.

C++ returning object created on heap and modifying it, doesnt change it?

I have following code
#include <iostream>
#include <vector>
using namespace std;
struct foo {
struct bar {
int foobar;
};
vector<bar*> barp;
bar & insert(int v){
bar * b = new bar();
(*b).foobar = v;
barp.push_back(b);
return *b;
}
void edit(bar & b, int v){
b.foobar = v;
}
};
int main() {
foo f;
foo::bar b = f.insert(5);
f.edit(b, 10);
std::cout << (b.foobar == 10?"true":"false") << std::endl;//now ok
std::cout << (b.foobar == 5?"true":"false") << std::endl;//now ok
std::cout << ((*f.barp[0]).foobar == 10?"true":"false") << std::endl;//after edit, still returns false
std::cout << ((*f.barp[0]).foobar == 5?"true":"false") << std::endl;//after edit, returns true
return 0;
}
Could someone explain me, why doesnt the "b.foobar" change to 10? Doesnt the b have the same address as the one saved in f.barp[0]?
EDIT:Thanks for answers, adding reference to void edit(bar & b, int v) does, of course, make sense. However adding reference to "bar & insert" doesnt seem to change anything, as the (*f.barp[0]).foobar stays unchanged after edit, even though insert should return reference now.
Doesn't the b have the same address as the one saved in f.barp[0]?
No, it does not. You return the object by value from the insert, i.e.
bar insert(int v)
^^^
Returning by value implies a copy: a new bar is constructed using a copy constructor, and the original one is discarded*.
To get the results that you expect, return bar& from insert:
bar& insert(int v) {
// ^
}
Similarly, edit should take its parameter by reference if you would like all functions to work on the same object.
* If it were not for you storing the pointer in a collection, this would also create a memory leak. Your program does have memory leak, too, but you can fix it by deleting objects in the barp vector.
Because you're passing the parameter to edit() by value, instead of by reference.
edit() ends up modifying a copy of the original object, which then immediately gets thrown away.
Also, you are returning a copy of the record from insert(), as well.
Your insert() must return a pointer, instead of a copy of the new record. You must also pass a pointer to edit(), too.
Doesnt the b have the same address as the one saved in f.barp[0]?
No, it does not. Every time you use bar with no further qualifications as an argument or return type, you are asking for a copy to be made. In this case, that means both the variable b in main and the variable b in edit are copies.
For this toy example, you can make the program do what you expected with these changes:
- bar insert(int v){
+ bar &insert(int v){
- void edit(bar b, int v){
+ void edit(bar &b, int v){
- foo::bar b = f.insert(5);
+ foo::bar &b = f.insert(5);
If you do not understand what that does or why, please consult a C++ textbook for an explanation of "references".
(If you've never seen the above -/+ notation before, it means "replace each line marked with a minus sign with the corresponding line marked with a plus sign.")
foo::bar b = f.insert(5);
This b object is different from *f.barp[0] since it is created from returned reference.
To make this work, change this line to
foo::bar& b = f.insert(5);
That way you are creating a reference to the object which you just inserted in the vector.

C++ bind to weak_ptr not working

I have a simple test where I am trying to bind a weak_ptr argument to a global function that takes a weak_ptr, and invokes a method if the backing pointer is still valid.
This seems to work when I create a lambda with the weak pointer. It also works if I call the global method directly, with the weak_ptr. However if I bind the global function to the weak_ptr in advance, it does not seem to work. Following watered down code illustrates the question.
I must be missing something simple. Any clues?
#include <iostream>
#include <functional>
#include <algorithm>
#include <memory>
using namespace std;
class MyValue : public enable_shared_from_this<MyValue>
{
public:
MyValue (int i)
{
value = i;
}
~MyValue()
{
}
int getValue() { return value; }
void printValue() { cout << value << endl; }
private:
int value;
};
void callWeakFunction (weak_ptr<MyValue> weakValue)
{
shared_ptr<MyValue> strongPtr = weakValue.lock();
if (strongPtr)
{
strongPtr->printValue();
}
else
{
cout << "Sorry, your backing pointer is gone" << endl;
}
}
int main()
{
weak_ptr<MyValue> weakValue;
// Try binding a global function to the weak pointer, doesn't seem to work
function<void()> weakPrintValue = bind(callWeakFunction, weakValue);
#if 0
// Create a lambda - this works fine
function<void()> weakPrintValue ([&weakValue]()
{
shared_ptr<MyValue> ptr = weakValue.lock();
if(ptr)
{
ptr->printValue();
}
else
{
cout << "Sorry, backing pointer is gone" << endl;
}
});
#endif
{
shared_ptr<MyValue> value = make_shared<MyValue>(7);
weakValue = value;
// Backing pointer is present
weakPrintValue(); // This does not work, but callWeakFunction (weakValue) works fine
}
// No backing pointer
weakPrintValue();
}
Resulting output:
Sorry, your backing pointer is gone
Sorry, your backing pointer is gone
Expecting the first weakPrintValue to print the value (7)
I think you want to wrap the weak_ptr in ref() to evaluate it lazily:
function<void()> weakPrintValue = bind(callWeakFunction, ref(weakValue));
I wouldn't expect either to work. In both cases you're capturing the initial value of weak_value when it is empty. To be affected by the subsequent assignment to it you need to capture by reference instead. So in the lambda you need [&weak_value], and for the bind you need
bind(callWeakFunction, cref(weakValue));
I believe bind() captures weakValue by value. It returns resulting object that has it's own copy of weakValue. When you change local weakValue it does not affect the copy inside of the object returned by bind().

use *this as std::shared_ptr

here is a "chess++" problem that I'm facing wright now with my nested class,
although it may look like some joke, it's not a joke but real problem which I want to either solve or change the way to achieve the same thing in my project.
#include <map>
#include <memory>
#include <iostream>
#include <sigc++/signal.h>
class foo
{
public:
struct bar;
typedef sigc::signal<void, std::shared_ptr<bar>> a_signal;
struct bar
{
bar()
{
some_signal.connect(sigc::mem_fun(*this, &foo::bar::func));
}
void notify()
{
some_signal.emit(this); // how to ??
}
void func(std::shared_ptr<foo::bar> ptr)
{
std::cout << "you haxor!" << std::endl;
// use the pointer ptr->
}
a_signal some_signal;
};
std::map<int, std::shared_ptr<bar>> a_map;
};
int main()
{
std::shared_ptr<foo::bar> a_foo_bar;
foo foo_instance;
foo_instance.a_map.insert(std::pair<int, std::shared_ptr<foo::bar>>(4, a_foo_bar));
foo_instance.a_map.at(0)->notify();
return 0;
}
What I want to do here is to emit a signal.
the signal is declared as one that triggers a handler that takes a shared_ptr as an argument.
the function notify() should convert *this into shared_ptr, how do I do that to make the above code run?
Derive from enable_shared_from_this:
struct bar : std::enable_shared_from_this<bar>
to get a member shared_from_this():
some_signal.emit(shared_from_this());
As long as the current object is owned by at least one shared pointer, this will return a shared pointer, sharing ownership with that pointer. Note that, in your program, a_foo_bar is empty, so neither this nor the call to notify will work. Also beware that it won't work from the constructor or destructor, since the object is not owned by a shared pointer at that time.

Does using .reset() on a std::shared_ptr delete all instances

I'm new to shared_ptr's and I'm trying to figure out the exact functionality of the .reset() function.
#include <memory>
#include <stdio>
using namespace std;
class SomeClass{};
int main()
{
shared_ptr<SomeClass> sp (nullptr);
//do some stuff, sp now has 10 co-owners
cout << sp.use_count << endl;
sp.reset();
cout << sp.use_count << endl;
return 0;
}
Would output
10
0
So since I used the reset function are all instances deleted from memory? As in, have I just eliminated any possible memory leaks with sp? Obviously this was a toy example that I quickly made up, sorry if it has any errors.
Follow up situation:
shared_ptr<SomeClass> returnThis() {
shared_ptr<SomeClass> someObject(new SomeClass(/*default constructor for example*/) );
return someObject;
}
somehere in main:
shared_ptr<SomeClass> mainObject;
mainObject = returnThis();
Does mainObject have a use count of 2 because someObject was created in a function but never cleared? Or is it one and the clean-up is done automatically when returning the value?
When you use .reset(), you are eliminating one owner of the pointer, but all of the other owners are still around. Here is an example:
#include <memory>
#include <cstdio>
class Test { public: ~Test() { std::puts("Test destroyed."); } };
int main()
{
std::shared_ptr<Test> p = std::make_shared<Test>();
std::shared_ptr<Test> q = p;
std::puts("p.reset()...");
p.reset();
std::puts("q.reset()...");
q.reset();
std::puts("done");
return 0;
}
The program output:
p.reset()...
q.reset()...
Test destroyed.
done
Note that p and q are both owners of the object, and once both p and q are reset, then the instance is destroyed.
No.
The whole purpose of shared_ptr is that you cannot delete it from one place if someone is using it in another. shared_ptr::reset() just decreases use_count by one and replaces its object by nullptr.
The .reset() method only applies to the object it's called upon.
It just replaces the pointer that variable is holding.