When move semantics works with std::move? - c++

How does move semantics work in this example:
struct test {
int ii[10];
int i;
};
test f() {
test a;
std::cout << "[1] " << &a << std::endl;
return a;
}
int main()
{
test x (f());
std::cout << "[2] " << &x << std::endl;
test x1 (std::move(x));
std::cout << "[3] " << &x1;
}
Output:
[1] 0x7fff50ac70c0
[2] 0x7fff50ac70c0
[3] 0x7fff50ac70f0
Why x was constructed using return value from f(), but x1 got different address than x?
Edit
struct test {
std::string s;
}
[...]
std::cout << (*void)&x.s[0];
I think I've understood eventually. Now addresses are the same.

This doesn't really have anything to do with move semantics. a and x have the same memory address because the copy is elided, so the return of f is allocated directly at the call site. x1 does not have the same address as x because it is a separate object, and separate objects cannot have the same address. Moving doesn't change the address, it allows the guts of your object to be ripped out and sellotaped into the moved-to object.

Related

String and function object

I encountered this issue, but I'm not sure what to make of it...
class Goo
{
char _ch;
string _str;
public:
function<void(void)> dobedo;
// Constructor 1
Goo(string s) : _str(s)
{
cout << "Constructed: [" << &_str << "]: " << _str << endl;
dobedo = [&]()
{
cout << "Dobedo: [" << &_str << "]: "<< _str << endl;
};
}
// Constructor 2
Goo(char ch) : _ch(ch)
{
dobedo = [&]() {
cout << "Dobedo: " << _ch << endl;
};
}
void show() { cout << "Show: [" << &_str << "]: " << _str << endl; }
};
int main()
{
string myStr1("ABCD");
string myStr2("EFGH");
vector<Goo> goos;
goos.push_back(Goo(myStr1));
goos.push_back(Goo(myStr2));
goos[0].dobedo();
goos[1].dobedo();
goos[0].show();
goos[1].show();
return 0;
}
For some reason, the function object wasn't able to print _str, despite being able to locate the memory address:
Constructed: [00EFF80C]: ABCD
Constructed: [00EFF7B0]: EFGH
Dobedo: [00EFF80C]:
Dobedo: [00EFF7B0]:
Show: [032F2924]: ABCD
Show: [032F296C]: EFGH
I did not have any problems with char variables though.
int main()
{
vector<Goo> goos;
goos.push_back(Goo('#'));
goos.push_back(Goo('%'));
goos[0].dobedo();
goos[1].dobedo();
return 0;
}
The output gives:
Dobedo: #
Dobedo: %
Any ideas?
You have undefined behaviour in your code without defining copy constructor. Default copy constructor copies all members by value. So your lambda object is copied and it holds references to destroyed object - _str (when vector had to be reallocated while calling push_back method).
Define copy constructor and move constructor for Goo class:
Goo(const Goo& g)
{
_str = g._str;
dobedo = [&]()
{
cout << "Dobedo: [" << &_str << "]: "<< _str << endl;
};
}
Goo(Goo&& g)
{
_str = move(g._str);
dobedo = [&]()
{
cout << "Dobedo: [" << &_str << "]: "<< _str << endl;
};
}
Your output clearly shows that the address of _str in constructor isn't the same as one in show. It means that your object was copied/moved. It may happen while it is pushed to a vector. BTW, it also may take place when you push/pop other elements to/from a vector as vector doesn't guarantee elements to stay at the same memory address.
When you create dobedo functor, all captured fields are copied to it. In the first case it was the address of _str which becomes invalid when the object is copied/moved (nobody updates it upon a move/copy!). Occasionally we may find an empty-string like stuff at that address (although accessing it is now a memory violation). In the second case, a character is captured and stored - and it definitely remains valid upon any object location change.

New pointer in class method must be casted into a reference

I have two classes, let's call them A and B
class A:
{
public:
//Some functions
A *getNewA() const;
private:
//some attributes
}
class B:
{
public:
//Some functions
private:
A &reftoA;
}
In the main code, I must generate a new A thanks to the A::getNewA() method. And this must go to B::reftoA, as written in class B.
Here is the A::getNewA() method :
A *A::getNewA()
{
A *newA = new A;
return newA;
}
OK. So now I call getNewA and want to store the results in reftoA, which is a reference to A. In a B function (which take a reference to A as parameter)
B::foo(A &paramA)
{
reftoA = *(paramA.getNewA());
}
I thought this should have been working, but it won't.
Because when dereferencing, reftoA will always take the this object and not the new allocated object.
Let's be clearer and let's modify the functions to output the results
A * A::getNewA()
{
A *newA = new A;
std::cout << "New pointer " << newA << std::endl;
std::cout << "this pointer" << this << std::endl;
return A;
}
void B::foo(A &paramA)
{
reftoA = *(paramA.getNewA());
std::cout << "new generated pointer " << &reftoA << std::endl;
}
Here is one of the output :
New pointer : 004FFAEC
this pointer: 0069D888
New generated pointer : 0069D888 //Expected : 004FFAEC
I can't get this "new generated pointer" to be the same than the new pointer the A::getNewA() returns after having allocated the memory. Of course, I guess there is some point with dereferencing the pointer to store it in a reference.
I know reference are used with existing object. Maybe the new object A::getNewA() should allocate memory for won't work as I expected.
I could use pointer instead reference in B::foo(), I know, but I can't
I think I am misunderstanding something about refrence and pointer, but I don't know what.
Any help greatly appreciated
The problem is that you can not reassign a reference. You can change only the value of the referenced object.
So you have to initialize the reference in the initializer list of the constructor of the class B.
Take into account that there is a typo in your code snippet
A*A::getNewA()
{
A *newA = new A;
std::cout << "New pointer " << newA << std::endl;
std::cout << "this pointer" << this << std::endl;
return A;
^^^^^^^^^
}
I think you mean
A*A::getNewA() const
^^^^^
{
A *newA = new A;
std::cout << "New pointer " << newA << std::endl;
std::cout << "this pointer" << this << std::endl;
return newA;
^^^^^^^^^^^
}
Always try to provide a verifiable complete example.
Here is a demonstrative program
#include <iostream>
class A
{
public :
//Some functions
A* getNewA() const
{
A *newA = new A;
std::cout << "New pointer " << newA << std::endl;
std::cout << "this pointer" << this << std::endl;
return newA;
}
private :
//some attributes
};
class B
{
public :
B( const A& a ) : reftoA( *a.getNewA() )
{
std::cout << "&reftoA " << &reftoA << std::endl;
}
private :
A& reftoA;
};
int main()
{
A a;
B b( a );
return 0;
}
Its output is
New pointer 0x2b392afbec20
this pointer0x7ffd287ad0af
&reftoA 0x2b392afbec20
As you can see the values of the New pointer and &reftoA are equal each other.
To make it more clear consider a very simple example
#include <iostream>
int main()
{
int x = 10;
int y = 20;
int &r = x;
r = y;
std::cout << "x = " << x << std::endl;
std::cout << "y = " << y << std::endl;
std::cout << "r = " << r << std::endl;
std::cout << std::endl;
std::cout << "&x = " << &x << std::endl;
std::cout << "&y = " << &y << std::endl;
std::cout << "&r = " << &r << std::endl;
return 0;
}
The program output is
x = 20
y = 20
r = 20
&x = 0x7ffd88ad47a8
&y = 0x7ffd88ad47ac
&r = 0x7ffd88ad47a8
This statement
r = y;
did not force the reference to refer the object y. It just reassigned the value of the referenced object x.
References have to be initialized when they are created.
Yes, you are misunderstanding something.
getNewA() is returning a pointer. it's not a smart pointer, you want to look into those and that's all I'll say on the matter.
on returning a pointer, you must keep a reference to this pointer else you will be unable to delete it and you'll get a memory leak. Thus you MUST have somewhere A* a = A::getNewA() and then later, when you no longer need it delete a;
Where you need to pass a reference to A, you can do foo(*a) which will dereference the pointer and pass a reference to the object it's pointing to.
But in summary, for all new code, smart pointers; there's no excuse to not use them.
Side note: Your code example had a few other issues; such as getNewA wasn't static; I'm going to take the code as a working example of your understanding, and not a working example.
Edit: On re-reading your example, the getNewA is intentionally non-static. I think this question is actually an XY problem (ie you're asking a question you've forced yourself into but isn't your actual problem); but I hope this addresses your misunderstanding of pointers and references.
You are not returning the pointer in the getNewA-Method
A* A::getNewA()
{
A *newA = new A;
return A; // you are returning A and not newA
}
And if you want to reassign the reference to a you can use a std::reference_wrapper
class B :
{
public :
void foo(A& paramA) {
reftoA = *(paramA.getNewA());
}
private :
std::reference_wrapper<A> reftoA;
}

std::move return value of weak_ptr::lock messing up reference count of shared_ptr?

i need an explanation of the following behaviour:
#include <iostream>
#include <memory>
#include <vector>
struct A {
std::string s = "foo";
std::weak_ptr<A> h;
std::shared_ptr<A> && getR() {
return std::move(h.lock());
}
std::shared_ptr<A> getL() {
return h.lock();
}
};
std::vector< std::shared_ptr<A> > storage;
std::vector< std::weak_ptr<A> > accountant;
void store(std::shared_ptr<A> && rr) {
std::cout << "store '" << rr->s << "' uses: " << rr.use_count() << std::endl;
storage.push_back(std::move(rr));
}
int main() {
// create keeper of A
auto keeper = std::make_shared<A>();
keeper->s = "bar";
// store weak_ptr-type handle with accountant
accountant.push_back(keeper);
// backref handle to A
keeper->h = accountant[0];
std::cout << "# case 0: manual 'move'" << std::endl;
{
store(std::move(accountant[0].lock()));
std::cout << "uses: " << keeper.use_count() << std::endl;
}
storage.clear();
std::cout << "# case 1: manual 'move' from internal" << std::endl;
{
store(std::move(keeper->h.lock()));
std::cout << "uses: " << keeper.use_count() << std::endl;
}
storage.clear();
std::cout << "# case 2: return copy from func" << std::endl;
{
store(keeper->getL());
std::cout << "uses: " << keeper.use_count() << std::endl;
}
storage.clear();
// all is well up to here.
std::cout << "# case 3: return rref from func" << std::endl;
{
store(keeper->getR());
std::cout << "uses: " << keeper.use_count() << std::endl;
std::cout << "storage[0]: " << storage[0].get() << " uses: " << storage[0].use_count() << " " << &storage[0] << std::endl;
std::cout << "keeper: " << keeper.get() << " uses: " << keeper.use_count() << " " << &keeper << std::endl;
}
storage.clear();
std::cout << "# after" << std::endl;
std::cout << "uses: " << keeper.use_count() << std::endl;
// all the A is gone!!!!
return 0;
}
output:
# case 0: manual 'move'
store 'bar' uses: 2
uses: 2
# case 1: manual 'move' from internal
store 'bar' uses: 2
uses: 2
# case 2: return copy from func
store 'bar' uses: 2
uses: 2
# case 3: return rref from func
store 'bar' uses: 1
uses: 1
storage[0]: 0x2b49f7a0fc30 uses: 1 0x2b49f7a10ca0
keeper: 0x2b49f7a0fc30 uses: 1 0x7ffd3683be20
# after
uses: 0
ideone: http://ideone.com/smt7TX
This is a class holding a weak_ptr to itself, so it can give out shared_ptr-handles to itself. Its a resource-class in the real code, and shared_ptr handles to those get passed around. Now in an effort to reduce copying shared_ptrs i came across my getHandle function (getR/getL in the above) and wanted it to return by moving instead of copying. In a short test std::moving the return of weak_ptr::lock seemed ok, but in the final code it messed things up bad.
In comparison to copying the return-value it seems moving it reduces the shared_ptr's reference counter - so i end up with 2 shared_ptrs in existence but both having a use_count() of 1. so if the one i got using get() goes out of scope the A gets destroyed and my original shared_ptr which is still around points to garbage.
In the example code you can see that after case 3 - i would have expected the last cout to tell me a use_count() of 1 until keeper is destroyed.
Now in the real code i just inlined the equivalent of getL in the hopes that this will prevent the superflous copying, but i can't get over not having a clue why this doesn't work as i thought it would.
Why does case 3 reduce the reference count?
And then why don't case 0 and 1 also reduce it?
You have a bug here:
std::shared_ptr<A> && getR() {
return std::move(h.lock());
}
This creates a temporary shared_ptr which is local to the function then returns a reference to it. That is a dangling reference to an object that no longer exists. Just return by value as getL does (I don't know why you've called it getL ... if that refers to an lvalue it's wrong, it returns an rvalue).
You are misusing std::move in a misguided attempt to improve performance, but simply returning the object is simpler, safer, and allows the compiler to optimise it far more effectively. Without the std::move there won't be any copy or move, the compiler will elide the temporary completely, see What are copy elision and return value optimization?
These other moves are also redundant (although not actually harmful here):
store(std::move(accountant[0].lock()));
store(std::move(keeper->h.lock()));
In both cases you're trying to move something that is already an rvalue, which is pointless.
Also you have reimplemented std::enable_shared_from_this, poorly. Get rid of your weak_ptr member and your backref and just do:
struct A : std::enable_shared_from_this<A> {
std::string s = "foo";
};
And then call keeper->shared_from_this() instead of keeper->getL(). You'll notice that shared_from_this() returns by value, not by reference, to avoid the bug in your getR() function.

C++ reference copying and assignment

I have few questions regarding below code
#include <iostream>
using namespace std;
class A
{
public:
A & add(A & b);
};
A & A::add(A & z)
{
A * a = new A();
A & b = *a;
cout << "Inside add, address of a: " << &a << endl;
cout << "Inside add, address of b: " << &b << endl;
cout << "Inside add, address of z: " << &z << endl;
A aa;
cout << "Inside, add, address of aa: " << &aa << endl;
return aa;
}
int main()
{
A *a = new A();
cout << "Original a: " << a << endl;
A & b = a->add(*a);
cout << "b: " << &b << endl;
return 0;
}
Q1. Inside main, line 3, a->add(*a), the same object pointed by pointer *a is passed. But inside the function A::add(A &), when i try to achieve the same effect via A &b = *a, i get a different object. Why is this so?
Q2. Inside A::add(A &), i return a non const reference to a local object aa and main gets the same memory address as the local reference. So this has the effect of extending the lifetime of local reference, beyond its scope.
Q3. Inside A::add(A &), i dereference *a multiple times, first via A &b = *a and then by return *a. In both cases, the memory address is always the same. How is this happening? You can check the output of &b inside A::add(A &)and the result of A &b = a->add(*a)
UPDATE:
The issue related to Q1 was that i was doing cout << &a, when i should have been doing cout << a
To eliminate return value optimization, i compiled with -fno-elide-constructors. I am using g++.
A1: You created a new *a with A* a = new A() The a in main is different than the a in A::add. The a in main is referenced by the variable z
A2: No, you created a on the heap, so it is going to last until you call delete on that variable
A3: A dereference does not change the memory location that is stored in the pointer, it just gets the value stored in that location. A reference is more like an alias. So &b is like saying &(*a)

Passing around an object in C++ by reference [duplicate]

This question already has answers here:
What are the differences between a pointer variable and a reference variable?
(44 answers)
Closed 9 years ago.
I have objects that I put into a std::vector. Later on I need to iterate through the vector and change some member variables in the objects in each position.
I think I want to pass the object once I have it by reference to a function to operate on it, but I seem to be getting an error:
Non-const lvalue reference to type 'Object' cannot bind to a value of unrelated type 'Object *'
Here is the general gist with code between omitted:
Object* o1 = Object::createWithLocation(p.x, p.y);
v.push_back(o1);
// later on
for (int f=0; f < v.size(); f++)
{
Object* obj1 = v.at(f);
addChild(h->createLayer(obj1), 3); // add the HUD
}
createLayer is defined at:
static PlantingHUD* createLayer(Object &o);
Can anyone explain my confusion between pointers and passing by reference? Do I have to do a cast of some sort?
static PlantingHUD* createLayer(Object &o);
this method need a reference to Object as the parameter,
but your input is a pointer.
Object* obj1 = v.at(f);
addChild(h->createLayer(obj1), 3); // add the HUD
That's the problem.
void foo(Object o)
Declares a function, foo, which will begin execution with a fresh, new, instance of class 'Object' called 'o'.
This is called "passing by value", but it's more accurately 'copying' because what foo receives is it's own, personal copy of the Object instances we call foo with. When "foo" ends, the "Object o" it knew, fed and put through school, will cease to be.
void foo(Object& o)
Declares a function, foo, which will begin executing with a reference to an existing instance of an 'Object', this reference will be called 'o'. If you poke or prod it, you will be changing the original.
This is called "pass by reference".
void foo(Object* o)
Declares a function, foo, which will begin executing with a variable, called "o", containing the address of what is supposed to be an instance of "Object". If you change this variable, by doing something like "o = nullptr", it will only affect the way things look inside foo. But if you send Samuel L Jackson to the address, he can deliver furious vengance that lasts beyond the lifetime of foo.
void foo(Object*& o)
Declares a function, foo, which will begin executing with a variable called "o", which is a reference to a pointer to an instance of object o - it's like an alias, except that without compiler optimization, it's actually implemented by the compiler using a sort of pointer.
Lets try these separately.
#include <iostream>
#include <cstdint>
struct Object
{
int m_i;
void event(const char* what, const char* where)
{
std::cout <<
what<< " " << (void*)this <<
" value " << m_i <<
" via " << where <<
std::endl;
}
// Construct an object with a specific value.
Object(int i) : m_i(i)
{
event("Constructed", "Operator(int i)");
}
// This is called the copy constructor, create one object from another.
Object(const Object& rhs) : m_i(rhs.m_i)
{
event("Constructed", "Operator(const Object&)");
}
// This is how to handle Object o1, o2; o1 = o2;
Object& operator=(const Object& rhs)
{
m_i = rhs.m_i;
event("Assigned", "operator=");
return *this;
}
// Handle destruction of an instance.
~Object() { event("Destructed", "~Object"); }
};
void foo1(Object o)
{
std::cout << "Entered foo1, my o has value " << o.m_i << std::endl;
// poke our local o
o.m_i += 42;
std::cout << "I changed o.m_i, it is " << o.m_i << std::endl;
}
void foo2(Object* o)
{
std::cout << "Foo2 starts with a pointer, it's value is " << (uintptr_t)o << std::endl;
std::cout << "That's an address: " << (void*)o << std::endl;
std::cout << "m_i of o has the value " << o->m_i << std::endl;
o->m_i += 42;
std::cout << "I've changed it tho, now it's " << o->m_i << std::endl;
}
void foo3(Object& o)
{
std::cout << "foo3 begins with a reference called o, " << std::endl <<
"which is sort of like a pointer but the compiler does some magic " << std::endl <<
"and we can use it like a local concrete object. " <<
std::endl <<
"Right now o.m_i is " << o.m_i <<
std::endl;
o.m_i += 42;
std::cout << "Only now, it is " << o.m_i << std::endl;
}
void foo4(Object*& o)
{
std::cout << "foo4 begins with a reference to a pointer, " << std::endl <<
"the pointer has the value " << (uintptr_t)o << " which is " <<
(void*)o <<
std::endl <<
"But the pointer points to an Object with m_i of " << o->m_i << std::endl <<
"which we accessed with '->' because the reference is to a pointer, " <<
"not to an Object." <<
std::endl;
o->m_i += 42;
std::cout << "I poked o's m_i and now it is " << o->m_i << std::endl;
// Now for something really dastardly.
o = new Object(999);
std::cout << "I just changed the local o to point to a new object, " <<
(uintptr_t)o << " or " << (void*)o << " with m_i " << o->m_i <<
std::endl;
}
int main()
{
std::cout << "Creating our first objects." << std::endl;
Object o1(100), o2(200);
std::cout << "Calling foo1 with o1" << std::endl;
foo1(o1);
std::cout << "back in main, o1.m_i is " << o1.m_i << std::endl;
std::cout << "Calling foo2 with &o1" << std::endl;
foo2(&o1);
std::cout << "back in main, o1.m_i is " << o1.m_i << std::endl;
std::cout << "Calling foo3(o2), which looks like the way we called foo1." << std::endl;
foo3(o2);
std::cout << "back in main, o2.m_i is " << o2.m_i << std::endl;
std::cout << "Creating our pointer." << std::endl;
Object* optr;
std::cout << "Setting it to point to 'o2'" << std::endl;
optr = &o2;
std::cout << "optr now has the value " << (uintptr_t)optr <<
" which is the address " << (void*)optr <<
" which points to an Object with m_i = " << optr->m_i <<
std::endl;
foo4(optr);
std::cout << "back in main, o2 has the value " << o2.m_i << std::endl <<
"and now optr has the value " << (uintptr_t)optr << std::endl <<
"and optr->m_i is now " << optr->m_i <<
std::endl;
if (optr != &o2)
delete optr; // otherwise we'd technically be leaking memory.
return 0;
}
Live demo on ideone.com.
Passing by Value
This term confuses people early in their C++ development because, in lay terms, it sounds like this is what "Object& foo" would do.
The term "pass by value" actually arises from what the language has to do to call such a function, to value-wise copy the whole of the original object/struct onto the stack or, in the case where a copy ctor is available, forward them to a value-wise constructor and recreate a copy of the original, value-by-value.
Pass-by-value should be used for most simple cases where you do not want side-effects on the values in your current scope from the function you are calling.
bool checkWidthdrawl(Dollars balance, Dollars amountToWithdraw)
{
// it's safe for me to change "balance" here because balance is mine
}
vs
bool checkWidthdrawl(Dollars& balance, Dollars amountToWithdraw)
{
balance -= amountToWithdraw;
if (balance < 0)
std::complaint << "My account seems to be missing $" << amountToWithdraw;
}
However, passing by reference can become expensive.
struct FourK { char a[1024], b[1024], c[1024], d[1024]; }
If you pass this around by value all day, you risk blowing up your stack at some point, as well as spending daft amounts of time copying all those bytes.
void foo(int i); // Unless you need to see the changes to i, this is perfectly fine.
void foo(FourK f); // Someone should hunt you down and yell "PEANUT" in your ear.
Passing by reference
References are really a contract over the pointer system that allow the language to ensure you're really talking about a concrete instance of an object, and thus allow you to refer to a pre-existing instance of a value outside of a function.
Of course, there are ways to break this, but the language tries very, very hard to make them difficult to do. For example, try adding this to the above code:
Object& makeObjectNotWar(int i)
{
Object thisObjectGoesAway(i);
return thisObjectGoesAway /*right about now*/;
}
You can also provide callers with an assurance that the function won't have any side effects on a variable with the "const" modifier.
void fooc(const Object& o)
{
o.m_i += 42; // Error
}
You can even use that within a function as a hint to yourself (and the compiler) that you don't want to accidentally change a value, here's a case where it can provide an optimization hint to the compiler:
std::vector<int> foo;
add1000valuesTo(foo);
const size_t fooSize = foo.size();
for (size_t i = 0; i < fooSize; ++i) {
// ... stuff you're sure won't decrease foo.size()
}
Without the const fooSize
for (size_t i = 0; i < foo.size(); ++i) {
The compiler has to start by assuming that "foo.size()" could be changed at any given iteration of the loop. It can probably figure out that it doesn't, but by giving it the hint, you've saved a little compile time, possibly improved your performance, and made it easier for a human to tell exactly what behavior you expected. Downside: If your loop does actually change the size of foo, you'll find out by bug reports :(
One last thing to know about pass-by-reference is that C++ references aren't protected or "ref counted". The language only promises that a reference will be valid for the duration of its scope, so long as you don't do anything stupid like, say, call something that deletes the object.
// Author intended this function to be called
// by the owner of a Dog.
void doneWithFoo(Dog& dog)
{
Dog* deadDog = &dog;
delete deadDog;
}
Rover& Babysitter::babysitDog(Dog& rover, int hours)
{
rover.feed(FeedType::Donut);
if (rover.pooped())
doneWithDog(rover);
// ...
return rover; // I have a bad feeling about this.
}
Obviously, you're not expecting "babysitDog" to result in the dog being disposed of. But bear in mind that because we passed in a reference, it to "babysitDog" that it's also gone from the caller too, and if that was using a reference... rover's dead, Dave, dead.
As with pointers, if you're going to store references beyond the scope in which you have access to them, then you become responsible for making sure the objects being referenced stick around or that the references are removed from the container before the objects do go away.