#include<iostream>
#include<vector>
struct Foo
{
int *nb;
Foo() :nb(new int(5)){}
~Foo(){ delete nb; }
Foo(Foo&& f)
{
std::cout << "Move\n";
nb = f.nb;
f.nb = 0;
}
};
std::vector<Foo> vec;
void func()
{
vec.push_back(Foo());
}
int main()
{
func();
std::cout << *(vec[0]).nb << "\n";
std::cin.ignore();
}
Running:
> ./a.out
Move
5
Is it normal that under VS2013 vec.push_back(Foo()); call Foo(Foo&& f) ?
I believed that Foo() was a lvalue.
This is normal. Since the instance that you create by calling Foo() is never assigned to a variable, the compiler will treat it as an r-value.
A short rule of thumb is that any object you create that is not given a name (ie no declaration) will be an r-value.
For a nice explanation of the details I recommend section 6.4.1 in The C++ Programming Language (4th Edition).
Related
Consider this:
#include <iostream>
#include <functional>
std::function<void()> task;
int x = 42;
struct Foo
{
int& x;
void bar()
{
task = [=]() { std::cout << x << '\n'; };
}
};
int main()
{
{
Foo f{x};
f.bar();
}
task();
}
My instinct was that, as the actual referent still exists when the task is executed, we get a newly-bound reference at the time the lambda is encountered and everything is fine.
However, on my GCC 4.8.5 (CentOS 7), I'm seeing some behaviour (in a more complex program) that suggests this is instead UB because f, and the reference f.x itself, have died. Is that right?
To capture a member reference you need to utilize the following syntax (introduced in C++14):
struct Foo
{
int & m_x;
void bar()
{
task = [&l_x = this->m_x]() { std::cout << l_x << '\n'; };
}
};
this way l_x is an int & stored in closure and referring to the same int value m_x was referring and is not affected by the Foo going out of scope.
In C++11 we can workaround this feature being missing by value-capturing a pointer instead:
struct Foo
{
int & m_x;
void bar()
{
int * p_x = &m_x;
task = [=]() { std::cout << *p_x << '\n'; };
}
};
You can capture a reference member in C++11 by creating a local copy of the reference and explicit capture to avoid capturing this:
void bar()
{
decltype(x) rx = x; // Preserve reference-ness of x.
static_assert(std::is_reference<decltype(rx)>::value, "rx must be a reference.");
task = [&rx]() { std::cout << rx << ' ' << &rx << '\n'; }; // Only capture rx by reference.
}
While porting some C++ code from Microsoft Visual Studio to gcc, I ran into a weird bug, which I eventually boiled down to this:
#include <iostream>
using namespace std;
class Foo {
public:
int data;
Foo(int i) : data(i)
{
cout << "Foo constructed with " << i << endl;
}
Foo(const Foo& f) : data(f.data)
{
cout << "copy ctor " << endl;
}
Foo(const Foo&& f) : data(f.data)
{
cout << "move ctor" << endl;
}
~Foo()
{
cout << "Foo destructed with " << data << endl;
}
};
int Bar(Foo f)
{
cout << "f.data = " << f.data << endl;
return f.data * 2;
}
int main()
{
Foo f1(10);
Foo f2(Bar(std::move(f1)));
}
If I compile and run the above code with Microsoft Visual Studio 2015 Community, I get the following output:
Foo constructed with 10
move ctor
f.data = 10
Foo destructed with 10
Foo constructed with 20
Foo destructed with 20
Foo destructed with 10
However, if I compile and run the code with gcc 6.1.1 and --std=c++14, I get this output:
Foo constructed with 10
move ctor
f.data = 10
Foo constructed with 20
Foo destructed with 10
Foo destructed with 20
Foo destructed with 10
gcc calls the destructor of f, the argument to Bar(), after Bar() returns, while msvc calls the destructor (apparently) before it returns, or at least before the constructor of f2. When is f supposed to be destructed, according to the C++ standard?
They are all right; it depends. It seems underspecified in the standard.
From [expr.call]/4 (this wording goes back to C++98);
The lifetime of a parameter ends when the function in which it is defined returns. The initialization and destruction of each parameter occurs within the context of the calling function.
And the CWG#1880;
WG decided to make it unspecified whether parameter objects are destroyed immediately following the call or at the end of the full-expression to which the call belongs.
Both the behaviour of g++ (and clang) and MSVC would be correct, implementations are free to pick one approach over the other.
That all said, if the code you have is dependent on this ordering, I would change it such that the ordering is more deterministic - as you have seen, it leads to subtle bugs.
A simplified example of this behaviour is;
#include <iostream>
struct Arg {
Arg() {std::cout << 'c';}
~Arg() {std::cout << 'd';}
Arg(Arg const&) {std::cout << 'a';}
Arg(Arg&&) {std::cout << 'b';}
Arg& operator=(Arg const&) {std::cout << 'e'; return *this;}
Arg& operator=(Arg&&) {std::cout << 'f'; return *this;}
};
void func(Arg) {}
int main() {
(func(Arg{}), std::cout << 'X');
std::cout << std::endl;
}
Clang and g++ both produce cXd and MSVC produces cdX.
I wanted to restrict a specific class to be creatable on the stack only (not via allocation). The reason for this is that on the stack, the object which lifetime has begun last, will be the first to be destroyed, and I can create a hierarchy. I did it like this:
#include <cstddef>
#include <iostream>
class Foo {
public:
static Foo createOnStack() {
return {};
}
~Foo () {
std::cout << "Destructed " << --i << std::endl;
}
protected:
static int i;
Foo () {
std::cout << "Created " << i++ << std::endl;
}
Foo (const Foo &) = delete;
};
int Foo::i = 0;
The constructor normally should push the hierarchy stack, and the destructor pops it. I replaced it here for proof of concept. Now, the only way you can use such an object is by storing it in a temporary reference like this:
int main() {
Foo && a = Foo::createOnStack();
const Foo& b = Foo::createOnStack();
return 0;
}
My question now is, how safe is this with the C++ standard? Is there still a way to legally create a Foo on the heap or hand it down from your function into another frame (aka return it from your function) without running into undefined behaviour?
EDIT: link to example https://ideone.com/M0I1NI
Leaving aside the protected backdoor, C++17 copy elision breaks this in two ways:
#include<iostream>
#include<memory>
struct S {
static S make() {return {};}
S(const S&)=delete;
~S() {std::cout << '-' << this << std::endl;}
private:
S() {std::cout << '+' << this << std::endl;}
};
S reorder() {
S &&local=S::make();
return S::make();
}
int main() {
auto p=new S(S::make()),q=new S(S::make()); // #1
delete p; delete q;
reorder(); // #2
}
The use of new is obvious and has been discussed.
C++17 also allows prvalues to propagate through stack frames, which means that a local can get created before a return value and get destroyed while that return value is alive.
Note that the second case already existed (formally in C++14 and informally long before) in the case where local is of type S but the return value is some other (movable) type. You can't assume in general that even automatic object lifetimes nest properly.
In this response, tloveless pointed out that it's possible in MSVC to use this->foo::foo(42); for constructor delegation to directly call a constructor:
#include <iostream>
struct foo
{
int m;
foo(int p) : m(p) { std::cout << "foo("<<p<<")\n"; }
foo()
: m(0)
{
this->foo::foo(42);
std::cout << "foo(), " << m << "\n";
}
};
int main()
{
foo f;
std::cin.ignore();
}
I was surprised that this even compiles in MSVC; clang++, g++ and me agree it's illegal, e.g. [class.ctor]/2 "Because constructors do not have names, they are
never found during name lookup"
However, MSVC doesn't even emit a warning with /Wall and without language extensions /Za in MSVC12 Update 1 (2013) and MSVC10 SP1 (2010).
The output is:
foo(42)
foo(), 42
in both versions. So there's no temporary created, but a constructor called.
Questions:
What is the name of this extension?
Isn't it considered an extension? (/Za and the list of extensions don't seem to think so)
Is there some documentation for / official description of this feature?
(I tagged this question with the [delegating-constructors] tag since it reminds me heavily of this feature)
meta-info: I'm almost sure this question is a duplicate, since this feature is somewhat known. For example, see this answer to a "similar question". Please do not hesitate closing this as a dup if you can find an answer that describes this feature.
It is not constructor delegating. Try following code:
#include <iostream>
class C{
public:
C() { std::cout << "C" << std::endl; }
~C() { std::cout << "~C" << std::endl; }
};
struct foo
{
int m;
C c;
foo(int p) : m(p) { std::cout << "foo("<<p<<")\n"; }
foo()
: m(0)
{
this->foo::foo(42);
std::cout << "foo(), " << m << "\n";
}
};
int main()
{
foo f;
}
According to output field "c" is initialized twice but destroyed only once. As zneak noted, It is similar to new (this) foo(42).
This is related to a question posted yesterday.
class A
{
public:
mutable int x;
A()
{
static int i = 0;
x = i;
i++;
std::cout << " A()" << std::endl;
}
~A()
{
std::cout << "~A()" << std::endl;
}
void foo() const
{
x = 1;
};
};
class B
{
public:
const A & a;
B(const A & a) : a(a)
{
std::cout << " B()" << std::endl;
}
~B()
{
std::cout << "~B()" << std::endl;
}
void doSomething()
{
a.foo();
};
};
int main()
{
B b((A()));
b.doSomething();
}
Now, a's destructor is called before the call to doSomething. However, the call works although the function basically changes a member of A. Is it not the same instance. No other A's are created. I used the static inside A's constructor to keep track of that. Can anyone explain?
This is undefined behavior, so there is no language standard explanation.
However, the destructor of A doesn't do anything to the memory area where x is stored, so if you look there later the value might just still be there. Or if you try to write to the address, the address is still there. You are just not allowed to do that.
Bo is correct.
In addition, you could check the address where 'A' is stored, and that should confirm that that address simply hasn't been reused yet (keep in mind a destructor frees ("releases") the memory, but doesn't traverse the data structure setting all of the bits back to 0; that would be inefficient).
If, for example, you find that A is stored on top of the stack, then you are simply fortunate that your subsequent function call doesn't pass in a parameter, as that would overwrite A's memory region.
Your reference is invalid after ~A() and it is undefined behavior
~A() calls destructors of all members of A in addition
Try so for example
class B
{
public:
const std::string & a;
B(const std::string & a) : a(a)
{
std::cout << " B()" << std::endl;
}
~B()
{
std::cout << "~B()" << std::endl;
}
void doSomething()
{
std::cout << "a = " << a << std::endl;
};
};
int main()
{
B b(std::string("I love C++ so much!"));
b.doSomething();
}
Expanding on Bo's answer.
For a temporary to exist, space will be reserved on the stack. This space is actually reserved as long as the semantics require the temporary to exist, and may then be reuse for something else.
If you were trying to use the memory after it has been reused, you would observe a strange behavior (the very definition of undefined behavior being that anything can happen). As it is, you luck out and the memory is still there, in the state you expect it to.
Example:
#include <iostream>
struct A {
A(): p(0) {}
~A() { if (p) { std::cout << *p << "\n"; } }
int* p;
};
int bar0();
void bar1(int i);
int main() {
A a;
{
int x = 4; a.p = &x;
}
{
int y = bar0(); bar1(y);
}
}
int bar0() { return 7; }
void bar1(int i) { std::cout << i << "\n"; }
Here, the compiler may choose to reuse the space of x for y, or just do anything it wants, and thus you're actually printing garbage.
Here is gcc 4.3.4 (and 4.5.1) output (courtesy of ideone):
7
4
Meaning that the space is not reused with those...