I'm trying to call a constructor of 1 object with the constructors for other objects, and am having a problem with things deleting. The important bits of code look like the following:
class command {
public:
command(const string& s) {
x = (char*) calloc(s.size()+1, 1);
memcpy(x, s.c_str());
}
~command() {
free(x);
}
private:
char* x;
}
this constructor mallocs a char* which needs to be freed in the destructor.
class pair {
public:
pair(command comm1in, command comm2in)
:comm1(comm1in), comm2(comm2in){};
private:
command comm1;
command comm2;
}
this one tries to set its 2 fields to the commands sent in.
I think it also calls their copy constructors (might be wrong though)
in another function, I call the constructor for pair like so
pair p(command("something"), command("something else"));
unfortunately, this has the effect of calling the destructors on the just created values and then the copy constructor in the constructor for pair.
Is there a good way to initalize comm1 and comm2 without going through the copy/delete process?
I think c++11 has rValue references and std::move but I don't know if those come into play here.
So I asked one of my professors about this and then played around. This was extremely helpful.
Here is what the above code should look like if we want to avoid double-freeing the pointer x.
command:
class command {
public:
command(const string& s) {
x = (char*) calloc(s.size()+1, 1);
strcpy(x, s.c_str());
}
command(command&& in): x(in.x) {
other.x = nullptr;
}
~command() {
if(x) delete x;
}
private:
char* x;
}
pair:
class pair {
public:
pair(command&& comm1in, command&& comm2in)
:comm1(std::move(comm1in)), comm2(std::move(comm2in)){};
private:
command comm1;
command comm2;
}
calling pair's constructor looks the same
pair(command("something"), command("something else"));
Learnings:
calling the delete constructor is unavoidable, so instead we must define a move constructor for command that gives it the R-value's pointer and sets the R-value's pointer to null. (so when its destructor is called it doesn't deallocate still-pointed-to memory)
To allow objects to be moved into another object, initialize them with std::move()
Why do this?
This allows for us to ensure that only that 1 instance of command will have the object.
We don't have to malloc / call new and get space on the heap.
the command is automatically deleted when pair is deleted, so we don't have to write a delete function
Related
I have code similar to this:
MyClass createInstance()
{
MyClass t;
t.setValue(20);
return t;
}
int main()
{
MyClass primary;
primary.setValue(30);
primary = createInstance();
}
My problem is that createInstance() creates a temporary that is deleted later. In my case, it doesn't use RVO, I have to use The Rule of Three (because my class has a pointer to data members), and I have to do a deep copy of Megabytes of data.
I wonder what's the best way to prevent the creation of a temporary?
Furthermore, I have this MyClass as a member of another class and I would like to prevent the indirection of a pointer and the requirement to manually delete it in the destructor of my parent class.
For example, I could use pointers instead (which would require me to explicitly call the destructor:
MyClass *createInstance()
{
MyClass *t = new MyClass();
t->setValue(20);
return t;
}
int main()
{
MyClass *primary = new MyClass();
primary->setValue(30);
delete primary;
primary = createInstance();
}
Or I could use a member function:
void MyClass::createNewInstance()
{
~MyClass();
init();
setValue(20);
}
int main()
{
MyClass primary;
primary.setValue(30);
primary.createNewInstance();
}
Or I could disallow Assignment/Copying in general:
void MyClass::createInstance()
{
setValue(20);
}
int main()
{
MyClass *primary = new MyClass();
primary->setValue(30);
delete primary;
primary = new MyClass();
primary->createInstance();
}
Am I missing something?
You can't (N)RVO copy into a pre-existing object. The optimization is all about using another freshly created object instead of copying, but in this case the compiler can't guarantee that the assignment object doesn't leave some of the existing state alone (for example).
I would expect that MyClass primary(createInstance()); would enable NRVO for you.
If you really need to assign from a create function your choices are at least two: You can create a temporary and then swap, avoiding the data copy. Alternately with C++11 you could move into the existing object.
Just like what paddy said, how do you know it's not using RVO?
The compiler will do many thing to optimize your code, if it's not in debugging mode.
But, in your creatInstance function, you create a local object, and call a member function on it. The calling of the member function ( t->setValue(20) ) makes it difficult to be optimized, because the compiler will think, the local object is more useful than just an return value. Clearly, we know the local t can be optimized out, but the compiler may not be able to analyze this from its context.
And, by the meaning of "creatInstance", it seems that you just want creat an instance and return it. So, if your constuctor allows to set the value directuly, you can use the RVO:
MyClass creatInstance()
{
return MyClass(20); // if your constuctor makes it possible
}
then, your code will be optimized to this:
// C++ psuedocode
void creatInstance(MyClass* ptr)
{
new (ptr) MyClass(20);
}
int main()
{
MyClass primary;
primary.setValue(30);
// primary = createInstance();
MyClass __temp; // default constructor not called!
creatInstance(&__temp);
primary.operator=(__temp);
// destruct the __temp
}
You may think, it still has to creat temporary object __temp and destroy it , yes, but in your original code, you will creat two temporary object and destroy them, one in your main stack frame, one in your creatInstance function's stack frame.
If you can not sustain the cost of creating temporary object and those stuff, I think you can just change your idea to this:
void modifyInstance(Myclass& objToBeModified)
{
objToBeModified.setValue(20);
// do any change
}
and call it by : modifyInstance ( primary );
by this way, the temporary object creation is definitely prevented!
After all, you just want to change the primary by calling a function, why not writting it directly like above?
My programming background is the Java world, but I've just started learning C++. I've stumbled across this rather trivial and probably pretty noobish problem that somehow puzzles me as a Java programmer:
I have a class with an array which is initialized via new in the constructor and deleted in the destructor. Now when I create an object of this class and assign another object of this class to the same variable (at least that is what I think it is), the delete[] method in the destructor seems to be called twice when the variables leave the scope (in this case the main() function) (the debugger gives me an _BLOCK_TYPE_IS_VALID assertion failed warning).
Why is that? Why isn't the deconstructor called before I assign a new object to f? How could I explicitely delete Foo(1)? What exactly happens here?
class Foo{
private:
int *field;
public:
Foo(int size){
field = new int[size];
}
~Foo(){
delete[] field;
}
};
int main(){
Foo f = Foo(1);
f = Foo(2);
}
There is something in the C++ world called the Rule Of Three.
A class will automatically generate a destructor, copy constructor, and assignment operator for you.
If you have to manually define one of those functions, you probably have to define all three of them.
In your case, you should define the two copy functions, so that a copy of Foo gets its own copy of field. Add these two functions:
class Foo{
Foo( const Foo &f ) {
size = f.size;
field = new int[size];
std::copy( f.field, f.field + size, field );
}
Foo& operator=( const Foo &f ) {
// Leverage the logic that was already written in the copy constructor
Foo tmp(f);
std::swap( *this, temp );
return *this;
}
};
Note that I'm assuming that you've stored size in the Foo object. You would probably need to store that information anyway in a real-life application
You're not following the rule of three, which is bad. Because the default copy constructor does a shallow copy, all your automatic variables (f and the temporaries) have the field member pointing to the same int, which is destroyed multiple times when the destructor is called.
Implement a proper copy constructor, or use C++ idioms and avoid manual management alltogether - i.e. use a std::vector instead.
What would make a field variable become obsolete before entering the destructor upon deletion of the object?
I was a looking for an answer for this problem I'm having on this site and came across this:
Lifetime of object is over before destructor is called?
Something doesn't add up at all: if I've declared a pointer to SomeClass inside another WrapperClass, when I construct the WrapperClass I need to create a new SomeClass and delete it on destruction of the wrapper.
That makes sense and has worked so far.
The pointer is still valid and correct well into the destructor otherwise obviously I wouldn't be able to delete it.
Now my problem is that my field members (both an int and a pointer to a SomeClass array) of WrapperClass are garbage when I call the destructor. I've checked the wrapper object just after construction and the data is fine. The wrapper is actually a pointer in another Main class and the problem occurs when I destruct that Main (which destructs the wrapper) but works fine if I just delete the wrapper from another method in Main.
My paranoia led me to the above mentioned answer and now I'm totally confused.
Anybody care to shed some light on what's really going on here?
EDIT:
Node is the SomeClass.
class WrapperException{};
class Wrapper {
private:
struct Node { /*....*/ };
int numNodes;
Node** nodes;
public:
Wrapper() : numNodes(0) { nodes = new Node*[SIZE]; }
Wrapper(const Wrapper& other) { throw WrapperException(); }
Wrapper& operator=(const Wrapper& other) { throw WrapperException(); }
~Wrapper() { //calling delete Main gets me here with garbage for numNodes and nodes
for(int i = 0; i < numNodes; i++)
delete nodes[i];
delete nodes;
}
};
class MainException{};
class Main {
public:
Main() { wrapper = new Wrapper(); }
Main(const Main& other) { throw MainException(); }
Main& operator=(const Main& other) { throw MainException(); }
~Main() { delete wrapper; }
private:
Wrapper* wrapper;
};
You need to use the Standard library to implement this behaviour.
class Wrapper {
private:
struct Node { /*....*/ };
int numNodes;
std::vector<std::unique_ptr<Node>> nodes;
public:
Wrapper() : numNodes(0) { nodes.resize(SIZE); }
// No explicit destructor required
// Correct copy semantics also implemented automatically
};
class Main {
public:
Main() : wrapper(new Wrapper()) {}
// Again, no explicit destructor required
// Copying banned for move-only class, so compiler tells you
// if you try to copy it when you can't.
private:
std::unique_ptr<Wrapper> wrapper;
};
This code is guaranteed to execute correctly. When in C++, if you have used new[], delete or delete[], then immediately refactor your code to remove them, and review three times any use of non-placement new- constructing a unique_ptr is pretty much the only valid case. This is nothing but a common, expected outcome of manual memory management.
Since Grizzly isn't answering, I'll put this out there.
Both your Main class and your Wrapper class need properly implemented copy constructors and assignment operators. See The Rule of 3.
The problem is, if your class ever gets copied(which is easy to happen without you even realizing it), then the pointers get copied. Now you've got two objects pointing to the same place. When one of them goes out of scope, it's destructor gets called, which calls delete on that pointer, and the pointed to object gets destroyed. Then the other object is left with a dangling pointer. When it gets destroyed, it tries to call delete again on that pointer.
The lifetime of your wrapper object has ended, but the integer and pointer sub-objects as well as the pointee are still alive. When you invoke delete on the pointer, the pointee's lifetime ends, but the pointer still remains alive. The pointer's lifetime ends after your dtor is complete.
Thus, if your members have become corrupted, there is something else afoot.
Node** nodes;
should be
Node * nodes;
Also the destructor is wrong. It should be:
for(int i = 0; i < numNodes; i++)
delete nodes[i];
delete [] nodes;
There might be other problems as well as e.g. you haven't created a copy constructor or assignment operator so that might make it so that the copy of an object then deletes the object for you.
EDIT: changed the destructor...
I have the following class:
class FixedByteStream {
public:
FixedByteStream() : size(0), address(NULL), existing(false) {}
FixedByteStream(int length) : existing(false) {
size = length;
address = new char[length];
}
FixedByteStream(int length, char* addr) : existing(true) {
size = length;
address = addr;
}
FixedByteStream(string* str, bool includeNull = false) : existing(true) {
size = (*str).length();
address = const_cast<char*>((*str).c_str());
if (includeNull){
++size;
}
}
~FixedByteStream() {
if (existing == false) {
delete [] address;
}
address = NULL;
}
int getLength() {
return size;
}
char* getAddressAt(int index) {
return &(address[index]);
}
char& operator[] (const int index) {
return address[index];
}
operator char*() {
return address;
}
private:
bool existing;
int size;
char* address;
};
And a very simple test that is able to produce the issue:
FixedByteStream received;
received = FixedByteStream(12);
received[0] = 't';
Valgrind warns about an invalid write, and debugging has shown why. FixedByteStream received; calls the constructor with no arguments (which is kind of stupid because it can't do anything). received = FixedByteStream(12); calls the constructor with the integer argument... and then immediately calls the destructor on itself, invalidating the object. It still works for some reason, but I'd rather it not be placed in such an odd predicament that throws warnings.
So, why is it being called there? I could somewhat understand if the destructor were called first, to get rid of the useless temporary object (not that it needs to), but I have used that kind of declare-now-assign-later pattern practically everywhere and never had such an issue before.
You are missing an assignment operator. Remember the rule of three (or five).
The problem is roughly like this:
T t; // default constructed t
t = T(2); // T(2) constructor with a single argument, assignment operator= called with this == &t
You provide no assignment operator so the pointer value in the temporary is simply copied into t and then the memory pointed to is deleted in the destructor of the temporary.
Also: Don't have a default constructor, if the object constructed is invalid.
If you object has any user defined constructor it is always constructed using a constructor. Just defining an object without any constructor arguments uses the default constructor independent of whether the object is being overwritten afterwards. That is
FixedByteStream received;
will call the default constructor. The next line is a bit more interesting:
received = FixedByteStream(12);
This line create a temporary FixedByteStream with the argument 12. Internally this will allocate some memory but since temporaries are destroyed at the end of the full expression (in this case essentially when the semicolon is reached) that won't you do much good. Once this temporary object is constructed it is assigned to received using the automatically generated copy assignment which would look something like this if you'd write it manually:
FixedByteStream& FixedByteStream::operator= (FixedByteStream& other) {
this->existing = other.existing;
this->size = other.size;
this->address = other.address;
return *this;
}
That is, once this assignment is executed, you have to identical copies of FixedByteStream, one of which is about to be destroyed and will release the resources just allocated. This is clearly not what you want, i.e. you definitely need to implement the copy assignment operator to make your class well-behaved. In general, the presence of a destructor which does anything interesting is a good hint at the fact that you'll need an assignment operator as well. In fact, there is another one of the generated operations, namely the copy constructor, which does roughly what the copy assignment does except that it copy constructs the members instead of assigning them. This is also not what you want with your class.
Now the interesting question becomes: how can FixedByteStream be fixed? Effectively, you'll need either to use reference counting to keep track of how many objects are currently looking at the FixedByteStream, allocate a copy of the content, or you need to use move semantic support (aka rvalue references) which is only available in C++2011. Unless you really know what you are doing I'd recommend copying the stream in all cases and leave a more advanced approach for later.
Step by step:
//create a new object using the default constructor
//I don't see why you think it's stupid that the constructor is called
//it's doing what you're telling it to do
FixedByteStream received;
//FixedByteStream(12) creates a temporary object
//you then copy this object in the received object you already have
//you're using the default operator =
//the temporary object is deleted after it is copied to received
received = FixedByteStream(12);
//received is a valid object
received[0] = 't';
EDIT:
As I see there's a lot of wrong answers for this question, I'll explain further. I might get some hate for this, but this is a pretty important concept and I downvoted so that a wrong answer doesn't get accepted and taken from granted.
You're basically initializing some object on the stack.
I'll simplify your case:
class A
{
A() {}
A(const A& other) {}
A& operator = (const A& other) {}
};
Let's talk about scope:
{ //begin scope
A a; //object a is created here
//default constructor is called
} //a is destroyed here
//destructor is called
So far so good.
Now, assignment:
{
//two objects are created with default constructor
A a;
A b;
//object b is assigned to a
//operator = will be called
//both objects are still alive here
a = b;
//...
} // a and b will be destroyed, destructor called
On to the last part:
{
A a;
a = A();
}
is pretty much equivalent to:
{
A a;
{
A b;
a = b;
}
}
When you call a = A(), A() creates a temporary object which is assigned to a and then destroyed.
So object b in my simplification is the temporary object that gets destroyed. Not a, your original, therefore a is still valid.
Not the assignment operator declaration. If you don't define one, a default is used. You probably want to write your own in this case.
FixedByteStream(12) is assigned to received through the default operator=. Notice that you didn't allocate FixedByteStream(12) in the heap by using new, but rather allocated it in local scope without specifying a name for the variable that would hold it.
Your code is somewhat similar to:
FixedByteStream received;
FixedByteStream temp(12);
received = temp;
received[0] = 't';
Only in my example temp has a name and its scope is the entire function, and in your test code temp doesn't have a name, it exists for one line only and then gets destroyed.
The FixedByteStream(12) object you've created cannot be used after this line because it's not even a named varaible.
Object is already initialized on this line
FixedByteStream received;
On line
received = FixedByteStream(12);
You reinitialize it. The correct way to do this is:
FixedByteStream received(12);
// Or
FixedByteStream *received;
received = new FixedByteStream(12);
(I'd definitely go for first one)
It seems you don't understand object lifecycle and mistakenly interpret this code as a Java code.
When you write FixedByteStream received; an object of type FixedByteStream is created using the no-argument constructor. And when you write received = FixedByteStream(12); another object is created, = operator is called and the newly created object is desctructed.
Also you didn't override operator= so the object is copied by bytes, which is not correct.
myClassVar = MyClass(3);
I expected destructor being called on the previously created myClassVar on the left.
But it is actually being called on the new object that's created by MyClass(3).
My full test code and output follows..
edit
How do I fix the problem?
Implement an assignment operator?
MyClass actually has pointers, and MYSQL_STMT*, I wonder how should I deal with MYSQL_STMT* variable.
I just need MyClassVar(3) object not the MyClassVar() which was first created when ClientClass object was created.
I came across this situation fairly often, and wonder if there's a good way to do it.
#include <stdio.h>
class MyClass
{
public:
MyClass() { printf("MyClass %p\n", this); }
MyClass(int a) { printf("Myclass(int) %p\n", this); }
~MyClass() { printf("~MyClass %p\n", this); }
private:
int mA;
};
class ClientClass
{
public:
void Foo()
{
printf("before &myClassVar : %p\n", &myClassVar);
myClassVar = MyClass(3); // this is the important line
printf("after &myClassVar : %p\n", &myClassVar);
}
private:
MyClass myClassVar;
};
int main()
{
ClientClass c;
c.Foo();
return 0;
}
MyClass 0x7fff5fbfeba0
before &myClassVar : 0x7fff5fbfeba0
Myclass(int) 0x7fff5fbfeb70
~MyClass 0x7fff5fbfeb70 // <--- here destructor is called on the newly created object
after &myClassVar : 0x7fff5fbfeba0
~MyClass 0x7fff5fbfeba0
Here's how the critical line breaks down:
myClassVar = MyClass(3);
First, MyClass(3) calls constructor and returns the object.
Second, myClassVar = copies the object to myClassVar.
Then the statement ends. The object (which is an immediate) is dead, and thus the destructor is invoked.
EDIT :
As for how to get around this. The only way I can think of is to use a placement new. I'm not sure if there's a better solution other than making a "set" method.
myClassVar = MyClass(3);
myClassVar continues to exist after this line. The lifetime of MyClass(3) ends at the semicolon.
As the other posts mentioned the object with the custom constructor MyClass(3) gets destroyed after the assignment operation myClassVar = MyClass(3). In this case you do not need a custom assignment operator because the compiler generated one copies the member mA to the already existing object myClassVar.
However since MyClass defines its own destructor you should adhere to the rule of three, which mandates that in such a case you should implement a custom assignment operator as well.
Responding to your edit: how do you fix what problem? It's not clear
what the problem is. If your class needs a destructor (and there's no
polymorphism in play), it probably needs both an assignment operator and
a copy constructor. Similarly, when "tracking" construcctions and
destructions, you should probably provide both as well, since they will
be called.
Otherwise: if the problem is that you're constructing and then
assigning, rather than constructing with the correct value immediately,
the simple answer is "don't do it". The compiler does what you tell it
to. If you write:
MyClass var;
var = MyClass(3);
you have default construction, followed by the construction of a
temporary, assignment, and the destruction of the temporary. If you
write:
MyClass var(3);
or
MyClass var = 3;
you only have one construction. (Note that despite appearances, there
is no assignment in the last snippet. Only construction.)
For class members, this difference appears in the way you write the
constructor:
ClientClass::ClientClass() { var = MyClass(3); }
is default construction, followed by creation, assignment and
destruction of a temporary;
ClientClass::ClientClass() : var( 3 ) {}
is just construction with the correct value. (Rather obviously, this
second form is preferred.)