Given example:
#include <iostream>
#include <cstdlib>
#define PRINT_NAME { std::cout << __PRETTY_FUNCTION__ << std::endl; }
namespace
{
struct A
{
A() { PRINT_NAME; }
~A() { PRINT_NAME; }
};
A f() { return {}; }
A b;
A && g() { return std::move(b); }
}
int
main()
{
std::cout << "------------------" << std::endl;
{
f();
std::cout << 1 << std::endl;
}
std::cout << "------------------" << std::endl;
{
A && a = f();
// or A const & a = f(); as mentioned in below discussion
std::cout << 2 << std::endl;
}
std::cout << "------------------" << std::endl;
{
A && a = g();
std::cout << 3 << std::endl;
}
std::cout << "------------------" << std::endl;
return EXIT_SUCCESS;
}
and its output (of clang 3.5.0):
(anonymous namespace)::A::A()
------------------
(anonymous namespace)::A::A()
(anonymous namespace)::A::~A()
1
------------------
(anonymous namespace)::A::A()
2
(anonymous namespace)::A::~A()
------------------
3
------------------
(anonymous namespace)::A::~A()
What is the semantic rule: an thinkable shortand of the standard's paragraphs, which compactly summarizes the difference in destructors behaviour regarding above code sample? I often faces "idiomatic rules" formulated via the "have some (non-obviously relevant) characteristic" or "have some inherent attribute" statements, e.g. "if it has a name, then it is an lvalue". Is there something similar?
This has nothing to do with rvalue references. In fact, if you change A&& to const A& throughout the code, the behavior won't change.
Probably your confusion is caused by the name of std::move() function. It doesn't actually move anything, it just casts its argument to rvalue reference.
Don't think about destructors, think about lifetime of objects. Personally I don't know a simple rule of thumb (apart from "read the standard"), but these three rules may help you:
Static objects have (basically) lifetime of the whole program.
If a temporary object returned from a function is not bound to anything, it's lifetime ends when the whole expression execution finishes.
If a temporary object returned from a function is bound to some reference, its lifetime is extended to a lifetime of that reference.
Related
I am having the below code :
std::vector<std::function<void()>> functors;
class Bar
{
public :
Bar(const int x, const int y):d_x(x),d_y(y){}
~Bar(){
cout << "Destructing Bar" << endl;
}
void addToQueue()
{
const auto job = [=](){
cout << "x:" << d_x << " y: " << d_y;
};
functors.push_back(job);
}
private :
int d_x,d_y;
};
void example()
{
cout << "Hello World" << endl;
{
shared_ptr<Bar> barPtr = make_shared<Bar>(5,10);
barPtr->addToQueue();
}
cout << "Out of scope. Sleeping" << endl;
usleep(1000);
functors[0]();
}
The output is as expected :
Hello World
Destructing Bar
Out of scope. Sleeping
x:5 y: 10
I am now capturing by value, which is why I assume when the Bar object gets destroyed, I can still access its member variables. If the above is right, I am expecting the below change to give me UB:
const auto job = [&](){
However, I still see the same result. Why is that? Have i understood something wrong?
EDIT Further on the above, what I want to understand from this example - is how can I have access to a class member variables in a lambda function even if object has been destroyed? I am trying to avoid UB and thought that passing by value is the way to go, but can't prove that the opposite isn't working.
This kind of confusion iss probably one of the reasons why C++20 deprecated the implicit capture of this with [=]. You can still capture [this], in which case you have the usual lifetime issues with an unmanaged pointer. You can capture [*this] (since C+=17), which will capture a copy of *this so you don't have lifetime issues.
You could also use std::enable_shared_from_this since you're using a std::shared_ptr in example, but that's a bit more complicated. Still, it would avoid both the copy and the UB when the lifetime issues.
In these examples you are capturing this and not any of the fields.
When capturing this, by design, it is never captured by copying the object or the fields.
The best way to capture a field by value is:
[field = field] () { }
Both versions of your code have undefined behaviour. barPtr is the only owner of the shared_ptr so your object is destructed at the end of the scope containing barPtr. Executing the lambda which has captured this from the object in barPtr has undefined behaviour.
The usual way to prevent this is for the lambda to capture a shared_pointer from shared_from_this to keep the object alive. E.g:
#include <vector>
#include <functional>
#include <iostream>
#include <memory>
std::vector<std::function<void()>> functors;
class Bar : public std::enable_shared_from_this<Bar>
{
public :
Bar(const int x, const int y):d_x(x),d_y(y){}
~Bar(){
std::cout << "Destructing Bar\n";
}
void addToQueue()
{
auto self = shared_from_this();
const auto job = [this, self](){
std::cout << "x:" << d_x << " y: " << d_y << "\n";
};
functors.push_back(job);
}
private :
int d_x,d_y;
};
int main()
{
std::cout << "Hello World\n";
{
std::shared_ptr<Bar> barPtr = std::make_shared<Bar>(5,10);
barPtr->addToQueue();
}
std::cout << "Out of scope\n";
functors[0]();
}
By capturing self the shared_ptr will now survive for at least as long as the lambda does.
#include <iostream>
#include <string>
#include <vector>
class X
{
public:
int& a;
int&& b;
X(int& c, int && d):a(c), b(std::move(d))
{
}
};
X* x = nullptr;
void fun()
{
std::cout<<"Fun\n";
int l = 8;
int r = 9;
std::cout << &(l) << std::endl;
std::cout << &(r) << std::endl;
x = new X(l, std::move(r));
}
int main()
{
fun();
std::cout << x->a << std::endl;
std::cout << &(x->a) << std::endl;
std::cout << x->b << std::endl;
std::cout << &(x->b) << std::endl;
}
=> Will values of member variable references (lvalue and rvalue) be garbage?
I am seeing different behavior across different compilers. So wanted to know what c++ standard says about this.
You're binding reference members to local variables, which will be destroyed when get out of the function fun(). After that, both references become dangled, any dereference on them leads to UB.
This is true for both lvalue and rvalue reference members.
I see the C++11 documentation (http://en.cppreference.com/w/cpp/language/lambda) for lambda expressions states capture by value and reference are supported but not rvalue reference. The closest SO question I could find related to this is: How to capture a unique_ptr into a lambda expression?, but it seems like my use case doesn't require the use of std::bind.
Code
#include <iostream>
#include <memory>
class Foo
{
public:
explicit Foo(int value = 0) : mValue(value) {}
// The following items are provided just to be explicit
Foo(Foo &&other) = default;
Foo &operator=(Foo &&other) = default;
Foo(const Foo &other) = delete;
Foo &operator=(const Foo &other) = delete;
~Foo() {}
int mValue;
};
void bar(std::unique_ptr<Foo> f)
{
std::cout << "bar: " << std::dec << f->mValue << "\n";
}
int main()
{
{
std::unique_ptr<Foo> f(new Foo(22));
std::cout << "main: " << std::hex << f.get() << "\n";
// Call the bar function directly (requires using std::move)
bar(std::move(f));
std::cout << "main: " << std::hex << f.get() << "\n";
}
{
std::unique_ptr<Foo> f(new Foo(99));
std::cout << "main: " << std::hex << f.get() << "\n";
// Lamda expression captures 'f' by reference and then calls the bar function (again, requires using std::move)
auto fn = [&f](){ bar(std::move(f)); };
fn(); // Execute the closure
std::cout << "main: " << std::hex << f.get() << "\n";
}
return 0;
}
Example Output
main: 0x92e010
bar: 22
main: 0
main: 0x92e010
bar: 99
main: 0
By examining the output it appears this program is running correctly (i.e., the observed results are what I expected. However, I have the following questions.
Questions
Is using the closure equivalent to the code that calls the bar function directly?
I'm asking explicitly since the documentation (see beginning of the question) about lambda expressions didn't state anything about using std::move on captured references (i.e., I want to make sure this doesn't run afoul of undefined behavior or similar bad outcomes).
If the answer to the first question is "you can't use std::move on the captured reference", then what is the right way to do this (e.g., the std::bind solution, etc)?
Is using the closure equivalent to the code that calls the bar function directly?
Yes, they're equivalent in this code. Captured references aren't special in any way that I can think of: you have fully defined behavior, as long as f is in scope and can be moved from.
Why only one object of A is created in this program? and no copy constructor is called. What is this optimization called? If this is a valid/known optimization, will it not be a trouble for multiton design pattern?
#include <iostream>
#include <stdio.h>
using namespace std;
class A
{
public:
A () {
cout << "in-- Constructor A" << endl;
++as;
}
A (const A &a) {
cout << "in-- Copy-Constructor A" << endl;
++as;
}
~A() {
cout << "out --Constructor A" << endl;
--as;
}
A & operator=(const A &a) {
cout << "assignment" << endl;
++as;
//return *this;
}
static int as;
};
int A::as = 0;
A fxn() {
A a;
cout << "a: " << &a << endl;
return a;
}
int main() {
A b = fxn();
cout << "b: " << &b << endl;
cout << "did destructor of object a in func fxn called?" << endl;
return 0;
}
Output of above program
in-- Constructor A
a: 0x7fffeca3bed7
b: 0x7fffeca3bed7
did destructor of object a in func fxn called?
out --Constructor A
Go through link http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
It will help you.
This seems to be a case of a return value optimization. This optimization is notable in the C++ world as it is allowed to change the observable behavior of the program. It's one of the few, if not the only, optimization that's allowed to do that, and it's from the days where returning copies was considered a weakness. (With move semantics and generally faster machines, this is much, much less of an issue now.)
Basically, the compiler sees that it's going to copy the object, so instead it allocates room for it on the calling frame and then builds it there instead of calling the copy constructor.
I have this class:
class Foo {
public:
Foo() {}
Foo(const Foo&){cout << "constructed by lvalue reference." <<endl; }
Foo(Foo&& ) {cout << "constructed by rvalue reference." << endl; }
};
then I insert into a vector:
Foo foo{};
vf.push_back(foo);
The output is surprising:
constructed by lvalue reference.
constructed by lvalue reference.
I assume it got copied when passing parameters, so I tried:
vf.push_back(move(foo));
and
vf.push_back(forward<Foo>(foo));
The output are slightly different due to move semantics but still calling constructor twice:
constructed by rvalue reference.
constructed by lvalue reference.
Why the constructors got called twice? How much performance does it impact? How can I avoid this?
I am using mingw-gcc-4.7.1 on Windows Vista
Total example:
#include <iostream>
#include <vector>
using namespace std;
class Foo {
public:
Foo() {}
Foo(const Foo&){cout << "constructed by lvalue reference." <<endl; }
Foo(Foo&& ) {cout << "constructed by rvalue reference." << endl; }
};
int main(int argc, char **argv, char** envp)
{
vector<Foo> vf;
cout << "Insert a temporary." << endl;
vf.emplace_back(Foo{});
Foo foo{};
cout << "Insert a variable." << endl;
vf.emplace_back(foo);
return 0;
}
Exact output:
Insert a temporary.
constructed by rvalue reference.
Insert a variable.
constructed by lvalue reference.
constructed by lvalue reference.
When you insert new items in a vector the vector may have to allocate more memory to fit those objects. When that happens it needs to copy all it's elements to the new memory location. That will invoke the copy constructor. So when you insert your element you're getting the constructor for that new element and the constructor when copying the previous element.
vector<Foo> vf;
cout << "Insert a temporary." << endl;
vf.emplace_back(Foo{});
What happens above is that a temporary Foo is created.
This temporary is then used to construct a Foo within the vector. So a "constructed by rvalue reference" is what you asked for.
If you wish to simply construct the Foo in place, try:
vs.emplace_back();
Next:
Foo foo{};
cout << "Insert a variable." << endl;
vf.emplace_back(foo);
here you construct a non-temporary foo. You then instruct the std::vector to construct a new element at the end of the list.
The interesting thing is that you get two construct by lvalue reference. The second seems to be caused by the resize. Why the resize causes you to be construced by lvalue reference, instead of rvalue reference, is a trick: if your move constructor is not marked noexcept, std::vector falls back on copy instead of move!
Here is a live example illustrating the above principles:
#include <iostream>
#include <vector>
using namespace std;
class Foo {
public:
Foo() {}
virtual ~Foo() {}
Foo(const Foo&){cout << "constructed by lvalue reference." <<endl; }
Foo(Foo&){cout << "constructed by non-const lvalue reference." <<endl; }
Foo(Foo&& ) noexcept {cout << "constructed by rvalue reference." << endl; }
};
int main(int argc, char **argv, char** envp)
{
vector<Foo> vf;
cout << "Insert a temporary. One move:" << endl;
vf.emplace_back(Foo{});
cout << "Insert a temporary(2). Two moves:" << endl;
vf.emplace_back(Foo{});
cout << "Resize with temporary(3). Two moves:" << endl;
vf.resize(10);
vector<Foo> vf2;
Foo foo{};
cout << "Insert a variable. One copy:" << endl;
vf2.emplace_back(foo);
cout << "Insert a variable(2). One move, one copy:" << endl;
vf2.emplace_back(foo);
cout << "Resize with variable(3). Two moves:" << endl;
vf2.resize(10);
vector<Foo> vf3;
cout << "Insert a nothing. No copy or move:" << endl;
vf3.emplace_back();
cout << "Insert a nothing(2). One move:" << endl;
vf3.emplace_back();
cout << "Resize with nothing(3). Two moves:" << endl;
vf3.resize(10);
}
A common implementation of std::vector::push_back looks like this:
void push_back(value_type _Val)
{ // insert element at end
insert_n(size(), 1, _Val);
}
As you can see, the input parameter is passed-by-value (so it is copied) in both the push_back declaration and the insert_n declaration. Hence, the copy-constructor is called twice.
After cleaning up your syntax:
#include <iostream>
#include <vector>
using namespace std;
class Foo
{
public:
Foo() {}
Foo(const Foo&) {cout << "constructed by lvalue reference." <<endl; }
Foo(Foo&&) {cout << "constructed by rvalue reference." << endl; }
};
int main()
{
vector<Foo> vf;
cout << "Size = " << vf.size() << endl;
cout << "Capacity = " << vf.capacity() << endl;
cout << "Insert a temporary" << endl;
vf.push_back(Foo()); // this is still very discouraged syntax
Foo foo;
cout << "Insert a variable." << endl;
vf.push_back(foo);
return 0;
}
You get the following output:
Size = 0
Capacity = 0
Insert a temporary
constructed by rvalue reference.
Insert a variable.
constructed by rvalue reference.
constructed by lvalue reference.
Press any key to continue . . .
In this example, I'm using a standard version of std::vector (which passes by const-reference or by reference-to-reference). The initial push_back call creates a capacity of 1 (and a size of 1). The 2nd call creates a new block of memory, moves the first item, and copies the second (the newly added) item.
In terms of performance, you aren't going to take a big hit for small reallocations. There are a few different common memory models used (the one with Visual Studio grows your capacity exponentially each time it has to grow to decrease the need for it in the future). If you know you will be starting with 100 elements, you should reserve space when you create your vector so allocation only happens once, which will also prevent the need to move existing elements when inserting new elements (due to the fact that you won't be exceeding your capacity multiple times).