I am a C programmer,
Now I am picking up C++ concepts (together with boost library).
please have look at my program and its output:
#include <boost/thread.hpp>
#include <iostream>
using namespace std;
class PowerClass
{
private:
int m, n;
public:
double *result;
PowerClass(int m, int n)
{
cout<<"I am in constructor " << this << endl;
this->m=m; this->n=n;
result = new double;
}
void operator () ()
{
cout<<"I am in () " << this << endl;
*result=m;
for (int i=1; i<n; ++i)
{
*result*=m;
boost::this_thread::yield();
}
}
};
int main()
{
PowerClass p(2,3);
cout<<"class created " <<&p<<endl;
boost::thread t(p);
t.join();
}
the out put is:
I am in constructor 0xbfcfe40c
class created 0xbfcfe40c
I am in () 0x9d0f154
The question could be more silly than plain:
I know () operator overloading function will be called upon thread creation, but why do I get a different address for the object (this) in the () operator, than the address of the same object in main() and constructor?
is this another copy of the object? why? how may I get work on the same object in () operator overloading function.
Thank you
You are passing the function parameter(which is your object) by value hence your overloaded function receives a copy of the object.
Of-course, the objects are places at different memory addresses and hence the different address.
You will need to pass the object by Reference to receive the same object inside your function.
Youre passing by value, instead of by reference, so the object is copied. hence the different address.
Add the following:
PowerClass(PowerClass const& copy)
: m(copy.m)
, n(copy.n)
, result(new double(*copy.result))
{
cout<<"I am COPY constructor " << this << " FROM: " << © << endl;
}
This will let you see the copy being made.
PS. You are leaking memory.
Edit: From comments below
I am in constructor 0xbf95cc30 class created 0xbf95cc30
I am COPY constructor 0xbf95cc3c FROM: 0xbf95cc30
I am COPY constructor 0xbf95cc04 FROM: 0xbf95cc3c
I am COPY constructor 0xbf95cb94 FROM: 0xbf95cc04
I am COPY constructor 0x941b184 FROM: 0xbf95cb94
I am in () 0x941b184
Question:
I notice that the I will finally have 2 copies(two object) ok. Any way, why do I get 4 messages of calls to the () overload function?
You don't you get 4 calls to the copy constructor (so there are actually 5 instances of the object around the program). Your object is being copy around inside thread most probably. If you add a print statement to the destructor you will see when they are being destroyed.
This usually happens when you don't have optimized tuned on (the optimizer can eliminate a lot of the default copying).
If you are using g++ then add -O3 If you are using MS tools build in release mode.
Related
I have a task to create an object Stos which would feature a heap of objects Obiekt, to which I could add things as I please.
In order to make the program better support dynamic arrays I decided to use a Vector.
The whole implementation seems to run perfectly, the returned value is completely off.
Here is an example with code:
class Obiekt {
private:
int id;
public:
Obiekt::Obiekt(int i) {
id = i;
}
void Obiekt::display() {
cout << "This object has id of: " << id << endl;
}
};
class Stos {
private:
vector < Obiekt* > stos;
public:
Stos::Stos(Obiekt n) {
add(n);
}
void Stos::add(Obiekt n) {
stos.push_back(&n);
}
void Stos::display() {
cout << endl << "===HEAP DISPLAY===" << endl;
for (int i = 0; i < stos.size(); i++) {
stos[i]->display();
}
}
};
void Zad1()
{
Obiekt obj1(5);
Obiekt obj2(23);
Stos s1(obj1);
s1.add(obj2);
s1.display();
getchar();
}
And the outcome being:
===HEAP DISPLAY===
This object has id of: -858993460
This object has id of:9805925
I'm not a cpp expert, and believe the issue is related to the stos.push_back(&n) portion, but I can't catch the moment the id gets so distorted.
It's probably a noob question, so sorry for that on start.
Any help would be amazing.
The issue with your code as O'Neil correctly explained is that you're adding the pointer to a copy of the Obiekt object. So basically, you create your object in main, and pass it to the constructor and the .add function in Stos. You then add the pointer to the vector. When the function finishes, the copy that was passed is destroyed and the pointer in your vector is dangling.
There are two ways to fix this:
1 Pass by reference
This is very simple, basically you just add an ampersand to your function parameters. For instance:
void Stos::add(Obiekt &n) {
stos.push_back(&n);
}
This will ensure that the object isn't destroyed at the end of the function
2 Don't use pointers
Another way of getting your problem to work is to avoid using pointers at all. Your vector will actually copy the contents of the Obiekt object into it. For example:
vector < Obiekt > stos; // notice how we define it without the pointer type
...
void Stos::add(Obiekt n) {
stos.push_back(n); // Creates copy which will then contain the correct value
}
The parameters Obiekt n in
Stos::Stos(Obiekt n) {
add(n);
}
void Stos::add(Obiekt n) {
stos.push_back(&n);
}
are temporary copies destroyed immediatly after each call.
You have to use a reference Obiekt & n instead, or better: by pointer Obiekt * n.
I'm reluctant to assert that the objects exist at the time display is called.
Problem(s)
According to GCC's implementation they don't.
They fall out of scope and are immediately destructed. Give "Obiekt" a non-trivial destructor and this behavior becomes obvious:
~Obiekt(){std::cout << "Bye from: " << it << std::endl;}
Secondarily, note that you shouldn't specify the class membership for functions defined within the class itself (no class_name::function_name(parameters), just function_name(parameters) )
Possible Fix
You (might) want to changing "Stos" such that:
Stos(Obiekt &n) {add(n);}
void add(Obiekt &n) {stos.push_back(&n);}
I was revisiting the concepts of structures in C++ before the lectures and written the following:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct isOdd{
bool operator()(int x){
return x%2;
}
};
int main(){
vector<int> v {3,4,2,1,65,2,4,65,2,9,8,5,7};
int count = count_if(begin(v), end(v), isOdd());
cout << "size of vector: " <<v.size() << endl;
cout << "count of odds: " <<count << endl;
return 0;
}
Then I realize that in calling function of structure isOdd, I have used the syntax: isOdd() but I have only overridden the () operator. So how the calling convention isOdd() is working because the calling a function of structure is like:
structure::function-name();
or structure-object.functions-name();
Can somebody elaborate the doubt?
Thanks.
Then I realize that in calling function of structure isOdd, I have
used the syntax: isOdd() but I have only overridden the () operator.
No, You called the implicit compiler generated default constructor, thereby creating a temporary object of isOdd.
For example: If you wanted to test it on a single number without creating a named isOdd object, you could:
bool is_odd = isOdd()(4);
//^^ Creates a temporary object
Optimizing Compilers will elide the creation of the temporary object since it neither has observable side effects nor a state.
I have the following code:
#include <iostream>
#include <memory>
#include <vector>
class Test
{
public:
Test() {}
~Test() { std::cerr << "Delete\n"; }
};
std::vector<std::shared_ptr<Test>> makeList()
{
std::vector<std::shared_ptr<Test>> list;
list.push_back(std::make_shared<Test>(Test()));
return std::move(list);
}
int main(int argc ,char **argv)
{
std::vector<std::shared_ptr<Test>> list;
std::cerr << "Before\n";
list = makeList();
std::cerr << "After\n";
return 0;
}
Which I compile with:
clang++ -std=c++14 -o ptr ptr.cpp
The output is:
Before
Delete
After
Delete
My question is: why is there an object being deleted in the makeList function? My assumption was that the list from the function would be moved into list from main and that therefore no object would be deleted/recreated in the process?
Can this be avoided (as obviously this code is not optimum)?
2 Changes:
std::vector<std::shared_ptr<Test>> makeList()
{
std::vector<std::shared_ptr<Test>> list;
// make_shared does not need a copy of an object, just constructor arguments
list.push_back(std::make_shared<Test>());
// return std::move(list) will defeat RVO. Never do that.
return list;
}
So, the important part is :
list.push_back(std::make_shared<Test>(Test()));
->
list.push_back(std::make_shared<Test>());
Just for clarification because I had the same today, and I had trouble seeing the difference.
list.push_back(std::make_shared<Test>(Test()));
Here temporary is created with Test(). Then copy c-tor for Test is invoked and temporary is destroyed. It is the first destructor call.
The second destructor call appears in the end of the program when list is destroyed.
The right form to avoid temporary creation is:
list.push_back(std::make_shared<Test>());
Besides you shouldn't use std::move returning the value because compiler cannot apply Return value optimisation in such case.
The line list.push_back(std::make_shared<Test>(Test())); makes a temporary Test and then moves it into the actual Test constructed by std::make_shared<T>. This temporary is then destroyed.
std::make_shared<T> requires the arguments to be used in construction of T. For a default constructed T simply provide no arguments.
The correct use, in this case, is this:
list.push_back(std::make_shared<Test>());
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am trying to understand the following code:
blueberry bitCopy(blueberry a) {
cout << "bitCopy " << blueberry::blQuantity << endl;
return a;
}
void howMany() {
cout << blueberry::blQuantity << endl;
}
int main() {
blueberry firstBl;
howMany();
bitCopy(firstBl);
howMany();
}
class blueberry:
#ifndef header_h
#define header_h
#pragma once
#include <string>
#include <iostream>
using namespace std;
class blueberry {
private:
static int blQuantity;
public:
blueberry();
~blueberry() {
blQuantity--;
}
friend blueberry bitCopy(blueberry a);
friend void howMany();
};
#endif
int blueberry::blQuantity = 0;
blueberry::blueberry() {
blQuantity++;
};
class blueberry is just some class that has a static int value blQuantity that increments in the constructor each time an object is created, and decrements in the destructor each time an object goes out of scope.
The read out from this program is:
1
bitCopy 1
-1
I was expecting 0 at the end rather than -1. Can someone explain this please?
PLEASE do not tell me I require a copy constructor. I am not trying to fix this code so that the object count works. I am instead trying to understand how this works and why the blQuantity is not the value I expect.
class blueberry is just some class that has a static int value blQuantity that increments in the constructor each time an object is created, and decrements in the destructor each time an object goes out of scope.
Are you sure that's each and every time one is created? I think there is something you've missed.
blueberry bitCopy(blueberry a)
That's pass-by-value; i.e., blueberry a here is a copy of what was submitted to bitCopy(). That invokes blueberry's copy constructor, which you have not defined. The compiler thus creates a simple one for you, which copies over any member values from the original object -- but it does NOT increment anything. If you want that, you'll have to define:
blueberry::blueberry (const blueberry&) // copy constructor
blueberry& operator= (const blueberry&) // copy assignment operator
You may also want a move constructor and move assignment operator -- see that wikipedia article about the "rule of three (or five)"
I linked in the above paragraph.
The reason blQuantity is -1 at the end is because there are actually two copies made with bitCopy(), one for the parameter and one for the return value. If you change it to:
blueberry bitCopy (blueberry &a)
I.e., using pass-by-reference, there will only be one copy and blQuantity will be 0 afterward. If you then make the return value void, there will be no copies made and blQuantity should be 1.
Here's a demonstration of the roles of the copy constructor and operator= (copy assignment operator):
#include <iostream>
#include <string>
using namespace std;
class A {
public:
string x;
A (string s) : x(s) {
cout << "A con " << "(" << x << ")\n";
}
A (const A& other) : x(other.x) {
x.append("-copy");
cout << "A copy " << "(" << x << ")\n";
}
A& operator= (const A& other) {
x = other.x;
x.append("[=]");
cout << "A assign " << "(" << x << ")\n";
return *this;
}
~A () { cerr << x << " A bye!\n"; }
};
A test (A a) {
return a;
}
int main (void) {
A a("#1");
cout << "test()\n";
A b = test(a);
cout << "Copy assign:\n";
b = a;
cout << "Exiting...\n";
return 0;
}
I'll step through the output from this:
A con (#1)
test()
A copy (#1-copy)
A copy (#1-copy-copy)
#1-copy A bye!
The first line is from A a("#1"). The last three lines are a result of A b = test(a). The first one is copying in the parameter, A test (test a). The second is the creation of the return value, which is a copy of the parameter, so the tag on the object is now #1-copy-copy. That initializes b in main(). When test() exits, the parameter object is destroyed, #1-copy A bye!.
Copy assign:
A assign (#1[=])
This is from b = a in main(). Notice that the previous version of b is not destroyed. This is because copy assignment is meant to turn one object into a copy of another; neither object is destroyed, but the contents of the target object is presumably changed, hence b's tag is now #1[=]. So predictably:
Exiting...
#1[=] A bye!
#1 A bye!
When the program ends, a and b are destroyed.
If you change the signature of test() to:
A& test (A &a)
You'll get this output:
A con (#1)
test()
A copy (#1-copy)
Copy assign:
A assign (#1[=])
Exiting...
#1[=] A bye!
#1 A bye!
Only two objects are ever created, a via the constructor and b via the copy con; both of them are not destroyed until the end. If you then do not use the return value of test(), only one object is ever created.
i am having trouble with my code. I am abit stumped.
I have a data member which is a pointer to a string type.
I use the constructor as a defualt initialer to this pointer, then when I call an object in the main function the intialised pointer to points to the memory address where the string is stored and prints the contents. That is what is supposed to happen, but I can't get the program to work. May somebody please tell me where I am going wrong?
#include<iostream>
#include<string>
using namespace std;
class NoName{
public:
NoName(string &sName("Alice In Wonderland") ){};
private:
string *pstring;
};
int main(){
//the constructor will be automatically called here once a object is created
// and the string "Alice in Wonderland" will appear on the screen
return 0;
}
Just simply use a std::string member and initialize it in Member initializer list:
private:
string mstring;
public:
NoName():mstring("Alice In Wonderland"){}
You could also let the constructor take in a parameter instead of hardcoding the string and let the user pass the string at run-time:
NoName(std::string str):mstring(str){}
You do not need a pointer. By using a pointer to std::string You nullify the advantages of implicit manual memory management offered by std::string.
If you really need to store a pointer for some reason, then there are some points to remember:
Pointers are initialized like new Class
Prefer to initialize class members in the member initializer list
Any time you write the word new think about where you're going to write delete. (In this case it goes in the destructor.
Rule of Three: If you need a destructor (you do, because of delete), then you also need a copy constructor and copy assignment operator.
This is one way your code could look: http://ideone.com/21yGgC
#include<iostream>
#include<string>
using std::cout; using std::endl;
using std::string;
class NoName
{
public:
NoName(string sName = "Alice In Wonderland") :
pstring(new string(sName))
{
cout << "ctor - " << *pstring << endl;
}
NoName(const NoName& rhs) :
pstring(new string(*rhs.pstring))
{
cout << "Copy ctor - " << *pstring << endl;
}
NoName& operator=(const NoName& rhs)
{
*pstring = *rhs.pstring;
cout << "Copy assignment operator - " << *pstring << endl;
return *this;
}
~NoName()
{
cout << "dtor, my name was " << *pstring << endl;
delete pstring;
}
private:
string *pstring;
};
.
int main()
{
NoName m, n("Another name");
NoName o(m);
o = n;
return 0;
}
Notice how much easier it is if you don't use the unnecessary pointer:
class Better
{
public:
Better(string sName = "Alice In Wonderland") :
m_string(sName)
{
}
private:
string m_string;
};
Because you don't need the custom destructor, you also don't need the copy constructor or copy assigment operator either. Much easier!
You're not using the constructor properly. First of all, you create this reference parameter and try to initialize it to a string object (that's asking for problems). Second, your constructor never actually does anything.
You need to call new on your pointer, dereference it and give the data pointed to a value, output the dereferenced value with std::cout and then clean the memory up with delete in the destructor (or in this case, you can do it after you use cout if you're not planning on using that string again. But do it in the destructor if you need it still).
Assuming you're doing this for a class, your textbook should tell you how to do these things.
EDIT: this is also not the default-constructor. I changed your tag to match appropriately.