I have such class, where I create a move constructor
class Test
{
private:
int m_a;
public:
Test(int val) { m_a = val; }
Test (const Test &) {}
// move constructor
Test (Test && d)
{
std::cout << &m_a << std::endl; // Line X
std::cout << &d.m_a << std::endl;
}
void print()
{
std::cout << m_a << std::endl;
}
};
I also create a function to test move constructor
void fun(Test a)
{ return ; }
Than in main function I create 2 objects of class above and call function to test move constructor
int main()
{
Test a {50};
Test b {100};
fun(a);
fun(std::move(a));
fun(b);
fun(std::move(b));
return 0;
}
When I looked at the output, I was surprised, because the address of o m_a variable in line X has same address for both objects.
0x7ffc40d37bb4 // look at this
0x7ffc40d37bac
0x7ffc40d37bb4 // look at this
0x7ffc40d37bb0
How is it possible ? It's not static member, what is going on ? Compiler optimization or what ?
Each time fun(Test a) is invoked, an instance of Test is created on the stack. Each time fun() returns, the stack frame is freed.
So when invoked twice in a row, the chance is great that you get an instance of Test created at exact same location on the stack.
If you wanted to take Test by reference, it should be void fun(Test&& a).
How is it possible ?
The parameters of the separate invocations of fun don't have overlapping storage lifetimes. Hence, they can use the same storage.
Related
English is not my native language,so please forgive me for my grammar problems.
When I run my program, I find that class constructors are called when defining objects and explicitly calling constructors。After calling the constructor and after leaving the scope, the destructor is called twice。
#include<iostream>
class test {
private:
int a;
int b;
int c;
public:
test(int first = 0, int second = 0, int third=0 );
void show();
~test();
};
void test::show() {
std::cout << this->a<<"\n";
}
test::test(int first , int second , int third ) {
this->a = first;
this->b = second;
this->c = third;
std::cout << "Construct\n";
}
test::~test() { std::cout << "destruct\n"; }
extern test myclassone;
#include <iostream>
#include "myhead.h"
test myclassone;
int main()
{
std::cout << "begain\n";
{
std::cout << "mid\n";
myclassone = test(1,1,1);
std::cout << "mid\n";
myclassone.show();
}
std::cout << "end\n";
}
The output of this program is
Construct
begain
mid
Construct
destruct
mid
1
end
destruct
In my expectation, constructors and destructors will only be called once. But what's puzzling is that according to the output, they were called twice.
I've googled this question, and many of the answers have not explained why the constructor is called when the object is defined, and why the destructor is called immediately after the constructor is called
Your program runs as follows:
The constructor is called for the global object test myclassone;.
main() is called.
begain and mid are printed.
The constructor is called for the temporal object test(1,1,1).
The temporal object is assigned to the global object.
The destructor is called for the temporal object test(1,1,1).
mid is printed.
myclassone.show() is called.
end is printed.
Return from main().
The destructor is called for the global object test myclassone;
Therefore the constructor and destuctor are called once for each objects and called twice in total.
I want to create a vector of "Act" objects that contain pointers to either "Eat" or "Drink" dynamically allocated objects. The new objects are being emplaced like so:
action_vector.emplace_back(Act::BehaviorType::eat);
However, it is seg-faulting and I can't figure out why. I thought that emplace_back would implicitly call the move constructor, not the destructor, but for some reason it is, which (I think) is what is screwing everything up.
Is there any way to successfully create a vector of such objects?
Here is the rest of the code along with its output. Sorry if it's a little verbose, but basically it's just a strategy pattern.
#include <iostream>
#include <vector>
class IBehavior
{
public:
IBehavior() = default;
virtual ~IBehavior() = default;
virtual void execute() = 0;
};
class Drink : public IBehavior
{
public:
Drink(): IBehavior() {}
~Drink() {}
void execute() { std::cout << "Drinking" << std::endl; }
};
class Eat : public IBehavior
{
public:
Eat(): IBehavior() {}
~Eat() {}
void execute() { std::cout << "Eating" << std::endl; }
};
class Act
{
IBehavior * b;
public:
enum class BehaviorType { eat = 0, drink = 1 };
Act() = default;
~Act()
{
std::cout << "Calling the destructor" << std::endl;
delete b;
}
Act(BehaviorType b_type) { SetBehavior(b_type); }
Act(Act&& act)
{
std::cout << "Calling the move constructor" << std::endl;
this->b = act.b;
}
void SetBehavior(BehaviorType b_type)
{
if(b_type == BehaviorType::eat) b = new Eat();
if(b_type == BehaviorType::drink) b = new Drink();
}
void execute() { b->execute(); }
};
int main(int argc, char * argv[])
{
std::vector<Act> action_vector;
for(int i = 0; i < 10; ++i)
{
action_vector.emplace_back(Act::BehaviorType::eat);
action_vector[i].execute();
}
return 0;
}
output:
Eating
Calling the move constructor
Calling the destructor
Eating
Calling the move constructor
Calling the move constructor
Calling the destructor
Calling the destructor
Segmentation fault: 11
Your move constructor copies b, and destructor deletes b, so if you move construct an instance then the same pointer value will be deleted twice which has undefined behaviour.
General solution: Use a smart pointer.
Another bug: Default constructor leaves b uninitialised. When a default constructed object is destroyed, the uninitialised pointer is deleted and behaviour is undefined. Smart pointer fixes this also.
Suppose we have a constructor which may throw exceptions.
class A{
public:
A(); // may throw exceptions
};
And we can use this way to catch the exceptions:
try{
A a;
// do somethings to a, and I have to put everything about a here
}catch(...){
// handle exceptions
}
So my question is how to avoid putting everything in the try-catch block, without using a pointer.
You could define a creation function that handles the exception for you, with a sensible default value to return in case of an exception, for example:
struct A
{
A() : data("Default")
{
std::cout << "In A()" << std::endl;
}
A(const A& other) : data(other.data)
{
std::cout << "In A(A)" << std::endl;
}
A(bool param)
{
std::cout << "In A(bool)" << std::endl;
if(param)
throw std::runtime_error("Failed");
data = "Hello";
}
std::string data;
};
A createA(bool param, A& def_a)
try
{
return A(param);
}
catch (...) {
//...
return def_a;
}
Then you can initiate your actual A with the return value of this function. Due to RVO, no copy will be performed if the creation is successful, only if it fails (as it will have to then copy the default value):
int main(int argc, char**args)
{
A defA;
A a1 = createA(true, defA);
A a2 = createA(false, defA);
std::cout << "A1: " << a1.data << std::endl;
std::cout << "A2: " << a2.data << std::endl;
return 0;
}
The output of this is:
In A()
In A(bool)
In A(A)
In A(bool)
A1: Default
A2: Hello
The first constructor is the default value. Then you can see after the first A(bool) call (which throws), a copy constructor call is made to return the default value. The second call, which doesn't fail, has no copy constructor call (due to RVO). After this you end up with a default A and a successfully created A which you can use thereafter.
Of course, if the copy constructor can also throw, then you might have an exception escape createA - if this is the case you would have to modify this design somewhat.
One possible approach is to use a sentry.
class sentry {
public:
bool exception_thrown=true;
void constructed()
{
exception_thrown=false;
}
~sentry()
{
if (exception_thrown)
{
// Whatever you want to do
}
}
};
Then:
sentry a_sentry;
A a;
a_sentry.constructed();
In the sentry's destructor, if exception_thrown is set, it could only be because an exception was thrown in A's constructor, because the flag gets cleared immediately after A gets fully constructed. So, put the cleanup code in the destructor. One thing you have to be careful with this approach is that the destructor itself cannot throw an exception of its own.
You can then also do things like:
class A_with_sentry : public sentry, public A {
public:
A_with_sentry()
{
constructed();
}
};
Then just declare:
A_with_sentry a;
Then, go a step further, and make this a template function, have the constructor perfect-forward its variadic parameters to the sentried object's constructor, etc...
There is other way but not recommended because you need to deal with pointers.
A* a=nullptr;
try {
a = new A();
}
catch(...){
}
if(a){
//do somethings to a, and I have to put everything about a here
delete a;
}
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.
I am trying to learn C++ and from what I've read in books and on SO:
If I use auto x = new Object(); x is a pointer to address of Object and this is in dynamic memory and exists until I delete it.
However if I use Object x; or auto x = Object() it only lasts until it goes out of scope.
In an example they have shown this:
void foo()
{
Point p = Point(0,0);
} // p is now destroyed.
What I don't understand is what happens when I return a object when I don't use new? Will it be a copy of the object?
Here is an example of what I am not sure about:
class Object
{
public:
int X;
static Object Foo(int y)
{
Object result;
result.X = y;
return result;
}
};
class TestContainer
{
public:
void Run()
{
for(auto i = 0; i < 10; i++)
{
_objects.at(i) = Object::Foo(i + (rand() % 10 + 1));
}
}
private:
std::vector<Object> _objects;
};
void main()
{
TestContainer tc;
while(true)
{
tc.Run();
}
}
Note I haven't tested this code but I think it illiterates my confusion. In my main function I instantiate TestContainer and endless call it's Run method. This in turn loops calling a static Foo method on Object that returns a copy of a new Object, which is stored in a vector.
My question is, what happens with all the Object's? If I replace element 2 in the objects vector with a new Object, is the old value now "out of scope" and is deleted?
Will it be a copy of the object?
Yes.
Or a move could be used instead, or the entire thing could be optimised away to produce only one actual object in your final, compiled program.
But, basically, yes.
If I replace element 2 in the objects vector with a new Object, is the old value now "out of scope" and is deleted?
Yes.
As an aside, you're using at on elements that don't exist; to add elements, use insert or push_back.
A simple class like this behaves much like a POD variable. o1=o2 copies the fields, element-wise. So the target Object of an assignment does not get deleted but overwritten.
Objects which go out of scope "go away" (because the stack is unwound) like e.g. an int.
Here is a run-able example that I believe illustrates this behavior:
#include <iostream>
using namespace std;
class Foo {
private:
int id;
public:
Foo(int x)
: id(x)
{
cout << this->id << " is created" << endl;
}
Foo(const Foo& rhs)
: id(rhs.id)
{
cout << "copied " << this->id << endl;
}
Foo& operator=(Foo rhs){
this->id=rhs.id;
cout << "assigned " << this->id << endl;
return *this;
}
~Foo(){
cout << this->id << " is destroyed" << endl;
}
int getID(){
return this->id;
}
};
Foo bar(){
Foo f1 = Foo(1);
cout << f1.getID() << " from bar" << endl;
return f1;
}
int main(){
Foo f2 = bar();
cout << f2.getID() << " from main" << endl;
return 0;
}
This produces this output:
1 is created
1 from bar
1 from main
1 is destroyed
From this, I'm not seeing a copy or an assignment. I suspect what is happening is that both f1 and f2 are referencing the same instance of the object in memory. The object is not being de-allocated when the f1 reference goes out of scope because the object has another reference assigned to it.