This is a standard pimpl in VS 2013:
.h:
#pragma once
#include<string>
#include<iostream>
#include <memory>
class TestClass01
{
private:
class impl;
std::unique_ptr<impl> pimpl;
public:
TestClass01();
TestClass01(int num, std::string str);
TestClass01(int num);
TestClass01(std::string str);
virtual ~TestClass01();
int ReturnMyInt();
std::string ReturnMyString();
};
.cpp
#include "stdafx.h"
#include "TestClass01.h"
#include <iostream>
class TestClass01::impl
{
public:
int myint;
std::string mystr;
};
TestClass01::TestClass01()
{
pimpl = std::make_unique<impl>();
}
TestClass01::TestClass01(int num, std::string str)
{
//pimpl = std::make_unique<impl>();
TestClass01();
pimpl->myint = num;
pimpl->mystr = str;
}
TestClass01::TestClass01(int num)
{
TestClass01();
pimpl->myint = num;
}
TestClass01::TestClass01(std::string str)
{
TestClass01();
pimpl->mystr = str;
}
TestClass01::~TestClass01()
{
std::cout << "Destroyed TestClass01 with int=" << pimpl->myint << " and str=" << pimpl->mystr;
}
int TestClass01::ReturnMyInt()
{
return pimpl->myint;
}
std::string TestClass01::ReturnMyString()
{
return pimpl->mystr;
}
The problem with this code is that it crashes if I call the default constructor from any other constructor instead of directly instanciating impl:
TestClass01::TestClass01(int num, std::string str)
{
//pimpl = std::make_unique<impl>(); -> This works, the line below doesn't
TestClass01();
pimpl->myint = num;
pimpl->mystr = str;
}
In the line below TestClass01(); pimpl is empty. But setting a breakpoint in the default constructor reveals that pimpl points to an object in the default constructor, becoming empty only when it leaves it.
What's causing pimpl to become empty? It's a member variable and it shouldn't get out of scope (and therefore cause unique_ptr to delete the containing object).
The proper syntax for constructor delegation in C++11 is
TestClass01::TestClass01(int num) : TestClass01() // <-- here, in the ctor
{ // init list.
pimpl->myint = num;
}
VS 2013 supports that, so this should work for you. The way you're doing it now just creates a nameless temporary TestClass01 object that's immediately destroyed and doesn't affect the current *this at all.
You can't call a constructor directly. When you try, all you're doing is creating an unnamed temporary that disappears after the call, and it doesn't affect the current object at all.
Here's some code that demonstrates it:
struct test
{
test() { cout << "default constructor on " << this << endl; }
test(int) { cout << "int constructor on " << this << endl; test(); }
};
int main() {
test t(1);
cout << "test object at " << &t << endl;
return 0;
}
See a demo at http://ideone.com/n2Thrn. The object pointers are output, notice that they're different.
Related
I am trying to make a deep copy of the object but for some reason I keep getting an error thrown at me.
Invalid address specified to RtlValidateHeap( 000002081EF60000, 000002081EF755C0 )
What does this mean? I have commented out the last two lines as this is not what causes the error but is what I would like to achieve.
#include "pch.h"
#include <iostream>
class Constant
{
public:
int Value;
Constant(int value) {
Value = value;
}
void set_value(int new_value) {
Value = new_value;
}
int get_value() {
return Value;
}
};
int main() {
std::shared_ptr<Constant> foo = std::make_shared<Constant>(1);
std::shared_ptr<Constant> bar(foo.get());
//bar->set_value(4);
//std::cout << (foo->get_value()) << " should be differnt than " << (bar->get_value());
return 0;
}
I expect the output "1 should be different from 4".
You are getting heap corruption due to a double-free problem. Your second shared_ptr is constructed with a raw pointer, which is already managed by the first shared_ptr. So both try to manage the same object, which leads to a double-free at the end of the scope.
To make a copy of an object in C++, just use copy construction:
#include "pch.h"
#include <iostream>
class Constant
{
public:
int Value;
Constant(int value) {
Value = value;
}
void set_value(int new_value) {
Value = new_value;
}
int get_value() {
return Value;
}
};
int main() {
Constant foo(1);
Constant bar(foo); // copy-construction
bar.set_value(4);
std::cout << (foo.get_value()) << " should be differnt than " << (bar.get_value());
return 0;
}
Note: in this example it is sufficient to rely on the default compiler-generated copy constructor.
Phil1970 got it right in the comments.
#include "pch.h"
#include <iostream>
class Constant
{
public:
int Value;
Constant(int value) {
Value = value;
}
void set_value(int new_value) {
Value = new_value;
}
int get_value() {
return Value;
}
};
int main() {
std::shared_ptr<Constant> foo = std::make_shared<Constant>(1);
std::shared_ptr<Constant> bar = std::make_shared<Constant>(*foo);
bar->set_value(4);
std::cout << (foo->get_value()) << " should be differnt than " << (bar->get_value());
return 0;
}
His solution allows you to use shared pointers and still obtain the desired result. Thanks Phil!
When you call this function:
std::shared_ptr<Constant> bar(foo.get());
You are directly taking the data pointer of the ptr internal and adding an additional controller(bar) to it. So don't pass the data ptr instead of the share ptr itself to the constructor.It should be like:
std::shared_ptr<Constant> bar(foo);
Flex Ferrum post a code sample here (I think it is Minimal, Complete, and Verifiable enough):
#include <iostream>
#include <functional>
using namespace std;
class Bang
{
public:
Bang(int i = 0) : m_val(i)
{
m_foo = [this] {std::cout << m_val << std::endl;};
}
~Bang()
{
m_val = -1;
}
void Foo()
{
m_foo();
}
private:
int m_val;
std::function<void ()> m_foo;
};
Bang GetBang()
{
return Bang(100500);
}
int main() {
Bang b(100500);
b.Foo();
b = GetBang();
b.Foo();
return 0;
}
Our nice Flex also offer a live demo
After a rough look, I thought it will output 100500, but the real output is:
-1
Why? What's behind it?
How to fix it?(output 100500, not -1)
I have written some my own reasonings in the ask box, but found it is more fit to be posted as an answer(will make the question too long). If my answer is wrong, please correct it and more answers are welcome
Ah, it should blame the destructor of temporary - Bang(100500), which returns form GetBang, is prvalue, and has temporary object lifetime.
[this] will be stored as reference of *this, like this:
class Lambda
{
public:
void operator()() const
{
//output
}
private:
Bang& bang;
public:
Lambda(Bang& bang) : bang{bang}
{
}
} lambda{*this};
...
m_foo = lambda;
Because here is no RVO, so, the temporary Bang(100500) will first be assigned to b, then be destroyed.
Custorm operator(), constructor, and destructor to output some information:
#include <iostream>
#include <functional>
using namespace std;
class Bang
{
public:
Bang(int i = 0) : m_val(i)
{
std::cout << "Bang(int i = 0) m_val address is " << &m_val << '\n';
class Lambda
{
public:
void operator()() const
{
std::cout << "operator() m_val address is " << &bang.m_val << '\n';
std::cout << bang.m_val << std::endl;
}
private:
Bang &bang;
public:
Lambda(Bang &bang) : bang{bang}
{
}
} lambda{*this};
m_foo = lambda;
}
~Bang()
{
std::cout << "~Bang()\n";
m_val = -1;
}
void Foo()
{
m_foo();
}
private:
int m_val;
std::function<void()> m_foo;
};
Bang GetBang()
{
return Bang(100500);
}
int main()
{
Bang b;
b = GetBang();
b.Foo();
return 0;
}
live demo
Output:
Bang(int i = 0) m_val address is 0x7ffd202c48b0
Bang(int i = 0) m_val address is 0x7ffd202c48e0
~Bang()
operator() m_val address is 0x7ffd202c48e0
-1
~Bang()
shows:
dtor will be called before output, That means that the temporary object has been destroyed.
m_value's address doesn't change.
The two guaranteed we still access the temporary's m_value from the b's m_foo().
It should be Undefined Behaviour to access an object which has be destroyed, but no warning and errors required.
Update
To solve the problem, there two solutions:
Like #Killzone Kid points out, capture with an initializer: [bang = *this]. This requires c++14.
More simpler way to capture of the current object by-copy: [*this]. This requires c++17. live demo
You probably want to pass current object to lambda by value *this so that it can be stored and copied when you copy assign Bang. Passing pointer this will store and copy pointer to the temp object that has been destroyed when you copy assign Bang.
This works as it should:
#include <iostream>
#include <functional>
class Bang
{
public:
Bang(int i = 0) : m_val(i)
{
m_foo = [bang = *this] { std::cout << bang.m_val << std::endl; };
}
~Bang()
{
m_val = -1;
}
void Foo()
{
m_foo();
}
private:
int m_val;
std::function<void()> m_foo;
};
Bang GetBang()
{
return Bang(100500);
}
int main()
{
Bang b;
b = GetBang();
b.Foo();
return 0;
}
Demo: https://ideone.com/LUDrBb
I wrote a program today which was giving me a real headache when it didn't work how I expected it to.
So I've written a short example which (almost)* reproduces the problem.
I hope this is fairly self-explanatory in what it is supposed to do.
#include <iostream>
class A
{
public:
enum class defaults
{
DEFAULT_A
};
A(defaults default_val)
{
if(default_val == defaults::DEFAULT_A)
{
A("hello world");
}
}
A(std::string str_)
{
str = str_;
flag = true;
}
std::string getStr()
{
return str;
}
bool getFlag()
{
return flag;
}
private:
bool flag;
std::string str;
};
int main()
{
A a(A::defaults::DEFAULT_A);
std::cout << a.getStr() << std::endl;
std::cout << a.getStr().size() << std::endl;
if(a.getFlag())
{
std::cout << "true" << std::endl;
}
else
{
std::cout << "false" << std::endl;
}
}
My compile and run code: g++ --std=c++14 main.cpp && ./a.out
Compiling on/with gcc version 5.2.1 20151010 (Ubuntu 5.2.1-22ubuntu2)
Output: [with line numbers]
1:
2: 0
3: true
(That first line is a blank line.)
*The only thing which is different from this example and the code I was working on today is that the flag in the code I wrote earlier was false not true, but this is still NOT what I expected it to be - I expected it to be true. And also, the string wasn't blank, but it did contain "nonsense values" - at least not what I expected it to contain.
What have I done wrong here? My guess is it's something really obvious, but I just can't spot it. (Perhaps I've been working on the same problem for too long now?)
Edit:
Can I do this to correct the problem?
A(defaults default_val)
{
if(default_val == defaults::DEFAULT_A)
{
*this = A("hello world");
}
}
To call a constructor from another constructor (a delegating constructor), you need to do it in the initializer list of the constructor:
A(defaults default_val) : A("hello world") {
.. more stuff to do after alling the delegate ctor
The problem is that this just allows you to make an unconditional call of the delegate ctor (though you can use ?: in the argument(s) to have their value be conditional.) There's no way to conditionally call the delegate.
If you always want to call the other constructor, you can move the logic that figures out the correct argument into another function.
Then you can use a delegating constructor as follows:
#include <cassert>
#include <iostream>
#include <string>
struct A
{
enum class defaults { first, second };
A(defaults default_)
: A(DefaultToString(default_))
{ }
A(const std::string & str)
: s_(str)
{ }
static std::string DefaultToString(defaults default_)
{
switch (default_)
{
case defaults::first: return "first";
case defaults::second: return "second";
}
assert(false);
}
std::string s_;
};
int main()
{
A a1(A::defaults::first);
A a2(A::defaults::second);
A a3("other");
std::cout << a1.s_ << " " << a2.s_ << " " << a3.s_ << "\n";
return 0;
}
A(defaults default_val)
{
if(default_val == defaults::DEFAULT_A)
{
A("hello world");
}
}
If this if statement is true, you're not calling this object's other constructor.
Here, A("hello world") constructs a new temporary object, using the given this constructor ... which is immediately destroyed, because this is a temporary object.
You may use helper function for your delegating constructor:
namespace {
A MakeA(defaults default_val)
{
return (default_val == defaults::DEFAULT_A) ?
A("hello world") :
A(/* other constructor*/);
}
}
A::A(defaults default_val) : A(MakeA(default_val)) {}
As currently, you create a unused temporary.
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.
I'm trying to make a class runner (run a class at a fixed time freq), which runs a class in another thread, and can be controlled (like pause, resume, stop) from main thread.
So I want to take advantage of C++11's Functor and other features. But I have a strange problem, the Functor's destructor passed into Runner has been called twice.
#include <iostream>
#include <chrono>
#include <thread>
using namespace std;
class Runner {
public:
typedef function<bool()> fn_t;
Runner(fn_t &&fn) : fn_(move(fn)), thread_(Thread, ref(*this)) {
cout << "Runner" << endl;
}
~Runner() {
cout << "~Runner" << endl;
thread_.join();
}
private:
fn_t fn_;
thread thread_;
static void Thread(Runner &runner) {
while (runner.fn_()) {
cout << "Running" << endl;
this_thread::sleep_for(chrono::milliumseconds(1));
}
}
};
class Fn {
public:
Fn() : count(0) {
cout << "Fn" << endl;
}
~Fn() {
cout << "~Fn" << endl;
}
bool operator()() {
return (++count < 5);
}
private:
int count;
};
int main (int argc, char const* argv[])
{
Fn fn;
Runner runner(move(fn));
return 0;
}
outpus:
Fn
Runner
~Fn
~Runner
Running
Running
Running
Running
Running
~Fn
~Fn
and if I change
Fn fn;
Runner runner(move(fn));
to
Runner runner(Fn());
the program outpus nothing and stalls. I have tried to disable compiling optimization, nothing changes. Any explanation?
How can I fix this or do the samething in other method? Should I implement this class like std::async / std::thread?
Update to Runner runner(Fn())
This statement was interrupted as a function declaration.
Runner runner((Fn())) solved problem.
Thanks for all comments and answers. After look into rvalue, seems I have misunderstand the meaning of rvalue reference from ground 0. I will try some other ways.
Final Solution for this problem
#include <iostream>
#include <chrono>
#include <thread>
#include <vector>
using namespace std;
template<typename T, typename... Args>
class Runner {
public:
Runner(Args&&... args) :
t(forward<Args>(args)...),
thread_(Thread, ref(*this)) {
cout << "Runner" << endl;
}
~Runner() {
cout << "~Runner" << endl;
thread_.join();
}
private:
T t;
thread thread_;
static void Thread(Runner &runner) {
while (runner.t()) {
cout << "Running" << endl;
this_thread::sleep_for(chrono::milliseconds(100));
}
}
};
class Fn {
public:
Fn() : count(0) {
cout << "Fn" << endl;
}
~Fn() {
cout << "~Fn" << endl;
}
bool operator()() {
return (count++ < 5);
}
private:
int count;
};
int main (int argc, char const* argv[])
{
//vector<Fn> fns;
//fns.emplace_back(Fn());
Runner<Fn> runner;
return 0;
}
outpus:
Fn
Runner
~Runner
Running
Running
Running
Running
Running
~Fn
Use std::move:
Runner(fn_t &&fn) : fn_(std::move(fn)), thread_(Thread, ref(*this)) {
/*....*/
}
You need to explicitly use std::move, otherwise it will be treated as a const reference. You could also use std::forward:
Runner(fn_t &&fn) : fn_(std::forward<fn_t>(fn)), thread_(Thread, ref(*this)) {
/*....*/
}
First of all, you shouldn't be taking r-value reference arguments for the most part, except in your own move constructors. As you have it, there is no way to pass l-values of std::function<bool()> into the constructor of Runner.
int main()
{
Fn fn;
std::function<bool()> func(fn);
Runner runner(func); // this is illegal
}
Maybe I'm just not creative enough, but I can't imagine any valid reason which you would want to prevent such a thing.
You should let std::function take care of its own copying/moving. When you need a copy of an object, take your parameter by value. If the function is passed an r-value, then it will be move constructed. If it is passed an l-value, then it will be copy constructed. Then, in your Runner constructor, you can move the value into the member object, as fontanini showed.
None of this is guaranteed to reduce destructor calls though, because when you move an object, you're still creating a second object, and will have to destroy a second object. In order to see fewer destructions, copy elision would have to happen, which actually does avoid the creation of multiple objects. But unlike moving, that's an implementation issue that's not guaranteed to come into effect in all the situations where you would hope.