I try to replicate C++ destructors and constructors in my c programming. That means for every object or struct there is an initialization function and a destruct function which frees all of the objects resources like so:
struct MyObject {
struct string a;
struct string b;
struct string c;
};
ConstructMyObject(struct MyObject *obj) {
ConstructString(&obj->a);
ConstructString(&obj->b);
ConstructString(&obj->c);
}
DestructMyObject(struct MyObject *obj) {
DestructString(&obj->a);
DestructString(&obj->b);
DestructString(&obj->c);
}
The destruct function is called at the end of every function scope just like in c++ only that i put it manually there. So now in DestructMyObject function I call the destructors of every struct string type because for the struct string object i would also have a destruct function written just like for the struct MyObject Object.
Example with my problem:
int main {
struct MyObject Object1;
ConstructMyObject(&Object1);
...
...
...
TransferOwnershipFunction(Object1.b); /*takes a struct string object as argument*/
...
...
...
DestructMyObject(&Object1);
return 0;
}
You see that i have transfered ownership of one Member of Object1 to another function but everything of Object1 will be destroyed by its destructor in the main function.
How do c++ destructors handle this kind of situation? I don't want that the destructor for struct string b is called at the end of main but it will be called because i call the destructor for MyObject. The function TransferOwnershipFunction(...) is now responsible for freeing the string object.
EDIT
Somebody knows how a rust compiler would resolve this issue? So in Rust would i need to clone the struct string object I'm passing to TransferOwnershipFunction or is there another way of doing it because cloning (or copying i guees) seems to be a very expensive operation.
From my point of view main() should be responsible for creating and deleting of Object1. And TransferOwnershipFunction() should work with a copy of Object1.b. In this case:
You need to create functions which work as analog of copy constructor and assignment operator (for C++03). Also move constructor and move assignment operator were added in C++11.
In C++03 copy constructor and assignment operator are generated implicitly if you don't declare them. By default they copy objects by member of class (not by bytes in memory) using copy constructor of each member (except simple types like int, double...). So you need to imitate of passing Object1.b by value with calling of copy constructor: in TransferOwnershipFunction create new object of type struct string, copy content of it by member. If struct string contains a raw pointer as member and you call malloc for this member in struct string's constructor and free in destructor than in copy constructor of struct string you need to call malloc than copy all content from passed variable. Don't forget to call destructor at the end of TransferOwnershipFunction.
According to RAII you need to call destructors in reverse order relation to order of creating objects (order of constructors).
Related
Why constructors and destructor are not called when pointer is created & destroyed ?
I m really confused because pointer is also an object just like normal object..memory is also allocated for pointer..then why constructor and destructor is not called of class
There is nothing to do in the construction of pointer objects, in much the same way as there is nothing to do in the construction of int objects, or of objects of a class that has a trivial constructor.
You can think of it like the (lack of) constructor for
class Trivial {
int member;
};
Creating a SomeClass calls the constructor of SomeClass if it has one. Creating an int calls the constructor of int if it has one. Creating a SomeClass * calls the constructor of SomeClass * if it has one.
You can write a constructor for SomeClass and then it will call it. int doesn't have a constructor so it doesn't call one. SomeClass * doesn't have a constructor so it doesn't call one.
SomeClass * isn't the same as SomeClass
Same for destructors.
(this explanation is simplified a bit)
Why constructors and destructor are not called when pointer is created & destroyed?
Because a pointer is not an object of type SomeClass but instead an object of type SomeClass*. In other words, when we create a pointer to some class-type say SomeClass then we're not creating an object of type SomeClass but of SomeClass*.
Constructor are called when an object of type SomeClass is created.
Basically,
//type SomeClass* is not the same as the type SomeClass
SomeClass* != SomeClass
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
What methods are called when we create an object of a class in c++ or what exactly happens when we create an object of a class.
Without additional information, you should assume that one and only one member function of the class itself is called, the constructor.
class CheesePizza {
public:
CheesePizza() {}
};
CheesePizza barely; // will initialize by calling Foo::foo().
There are many cases in which additional functions might be called, for instance if you create a conversion scenario where a temporary object must be created, such as specifying a std::string argument and passing a const char* value.
class DIYPizza {
std::string m_toppings;
public:
DIYPizza(const std::string& toppings) : m_toppings(toppings) {}
};
DIYPizza dinner("all of the toppings");
This has to create a temporary std::string from the const char* argument, "all of the toppings". Then the DIYPizza::DIYPizza(std::string) operator can be passed this temporary (rvalue), and then subsequently we initialize m_str from it which invokes the std::string(const std::string&) copy constructor to initialize m_str.
What essentially gets done is:
// create a std::string object initialized with the c-string.
std::string rvalueString = std::string("all of the toppings");
// now we have a string to pass to DIYPizza's constructor.
DIYPizza dinner(rvalueString);
However - we're still only calling ONE member function of Foo at this point. The only way for more class members to be invoked is by calling them from whichever constructor is invoked.
class DinnerAtHome {
void orderPizza();
void drinkBeer();
void watchTV(); // I was going with something more brazen, but...
public:
DinnerAtHome() {
orderPizza();
drinkBeer();
watchTV();
drinkBeer();
// arrival of pizza is handled elsewhere.
}
};
Now when you construct a new DinnerAtHome, 5 member functions will be invoked: DinnerAtHome::DinnerAtHome() and the four member-function calls it makes.
Note: "new" is not a member function, it is a global operator.
IF the answer was "five" then either the interviewer was using a trick question or you missed some nuance of what was being asked.
Ok I try overkill answer since no once already selected an answer:
When you create an object the constructor is called, this also involves a call to underlying constructors of members objects, if the object inherits from another object you need also to call constructors of base classes
class Foo: public Bar{
std::vector<int> indices; //default constructor for indices is called
public:
Foo(int a):Bar(a){ //you have to call constructor of Bar here
//else compiling error will occur
}
};
Default constructor is called implicitly for objects that has it. When you create something with "new", first memory is allocated then object is constructed on top of that memory (placement new works in a similiar way, but the chunk of memory may be created explicity by the user elsewhere).
Note that in certain cases you don't know order of constructors calls:
CASE 1
Obj1* myobj= new Obj1 ( new Obj2, new Obj3( new Obj4) );
in this case you have no clues if Obj4 is created before or after Obj2 and if Obj3 is created before or after Obj2, simply the compiler will try to choose "an order" (that may vary depending on compiler and platform), also this is a highly unsafe code:
assume you get exception in Obj3 when Obj2 was already created, then Obj3 memory will never get deallocated (in that extreme case you may find usefull tools for those kinds of problems : Hypodermic / Infectorpp )
see also this answer
CASE 2
static/global variables may be initialized in different orders, and you have to rely on specific compiler functions to declare a initialization order
for GCC:
void f __attribute__((constructor (N)));
also note that "Constructor" is not a "method" like others, infact you cannot save constructor in a std::function nor bind it with std::bind. The only way to save a constructor is to wrap it with a factory method.
well that should be 5 "things" as you mentioned in the interview.
Lets assume your class is called CMyClass.
#include "MyClass.h"
/* GLOBAL objects */
static CMyClass g_obj("foo"); // static makes this object global to this file. you can use it
// anywhere in this file. the object resides in the data segment
// (not the heap or the stack). a string object is created prior
// to the constructor call.
int main(void)
{
....
if (theWorldEnds)
{
/* STACK */
CMyClass obj1; // this calls the constructor CMyClass(). It resides on the stack.
// this object will not exist beyond this "if" section
CMyClass obj2("MyName"); // if you have a constructor CMyClass(string&), the compiler
// constructs an object with the string "MyName" before it calls
// your constructor. so the functions called depend on which
// signature of the constructor is called.
/* HEAP */
CMyClass *obj3 = new CMyClass(); // the object resides on the heap. the pointer obj3
// doesn't exist beyond the scope of the "if" section,
// but the object does exist! if you lose the pointer,
// you'll end up with a memory leak. "new" will call
// functions to allocate memory.
}
}
If you are creating a class means you are calling constructor of that class. If constructor is not in your code than compiler will add the default constructor. YOu can override default constructor to perform some task on object creation.
For
Example:
If you are creating a object of type Person
Person* objPerson = new Person();
It means you are calling Person() method(constructor) of that class.
class Person {
public:
Person() {
// ...
}
};
When an object of a class is instantiated : memory required by the object of the class (depending on its data members) is allocated on the heap and a reference to that memory location is stored by the object name. This individual data members at this memory location on the heap may or may not be initialized depending on the constructor called.
When a new object is constructed, the constructor of the class is invoked to initialize non-static member variables of the class (if the class does not have any constructors, compiler assigns a an empty constructor for the class and invokes it). The constructor may invoke other functions (either library or user-defined functions), but that depends on the functions that programmer has invoked inside the constructor. Also, if the class is part of an inheritance hierarchy, appropriate constructor of base classes are called by compiler before the constructor of the class being instantiated (visit here for a brief explanation).
Short version: Can I safely create a copy constructor for a class that has member pointer variables, one of which is on the heap, that are of type xercesc::XercesDOMParser* and xercesc::DOMDocument*? If so, how?
Long version:
I wrote a class to wrap a Xercesc document object. It has two member variables that are pointers to a XercesDOMParser and a DOMDocument. Here is the part of the class declaration that shows those two members:
class XMLigator {
private:
xercesc::XercesDOMParser* _pParser;
xercesc::DOMDocument* _pDocument;
etc...
The pointers _pParser and _pDocument are initialized in the constructor. Here is an abbreviated version of the constructor with the relevant code. Notice that _pParser is created with the new operator and is on the heap:
XMLigator::XMLigator(string strFile) : _strFile(strFile), _pDocument(NULL) {
xercesc::XMLPlatformUtils::Initialize();
_pParser = new xercesc::XercesDOMParser();
_pParser->parse(_strFile.c_str());
_pDocument = _pParser->getDocument();
}
The destructor deletes the member variable _pParser:
XMLigator::~XMLigator(void) {
if (m_pParser) {
delete _pParser;
}
}
Until now I have prohibited the copy constructor and assignment operator by marking them private and not defining them.
Now I would like to, if possible, create a copy constructor for this class so I can make it a return type for a function, in this fashion:
XMLigator getOne() {
XMLigator xml("/some/file.xml");
return xml;
}
The first problem I see is my the destructor does a delete _pParser;. So I think that's a problem. I am pretty sure I have to remove the delete from the destructor. But then I have a memory leak.
I really have no idea how to approach this. Maybe it's not possible. Does anyone have an approach that I can use for this?
Hi I have a class which includes an array, I'm not passing this through my class constuctor (could be going wrong here?) The array is just defined in the class then initialized in a read method.
But in the main I make an instance of the class like:
myClass myClass1;
Then do:
myClass1 = myClass2;
Now I use a bubble sort method on the first class instance like:
MyClass1.sort();
Now when I write both of these instances out to text after the sort they are both sorted?
I have had a read into shallow and deep copys, but I can't understand why a method called after the shallow copy, would result in both of them being sorted? Is this expected behavoir?
a little more information:
In my class I just define the array as:
static string myArray[5];
then in a write method I write the 5 elements to it, is there a better way of doing this, I have to use a method to intialize it though.
How is your array defined/created? If you create it with new and reference it with a pointer, you'll need a custom copy constructor creating a deep copy (i.e. creating a new instance of the array and copying its contents). The default copy constructor will only do a shallow copy, so both instances would use the same memory (i.e. both pointers' point to the same array on the heap).
This will work with the default copy constructor:
class myclass {
char text[256];
}
This won't work with the default copy constructor (at least not as expected):
class myclass {
char *text;
myclass() : text(new char[256]) {}
~myclass() { delete [] text; }
}
A member defined as static will never be copied. All instances share it without further code required:
class myclass {
static char text[256];
}
A copy constructor for the second case could look like this (note this is simplified and not checking for valid values and such):
myclass(const myclass &base) : text(new char[256]) { strcpy(text, base.text); }
General rule of thumb:
Do I use any pointer member that is assigned the return value of some new? If so, write a copy constructor. If not, hen use he default one (unless you've got other reasons).
In my class I just define the array as:
static string myArray[5];
Should I declare it in the header, as its only declared in the cpp file? As its still copying both.
If you declare that outside of a class definition it will be a global variable. There will only be one instance of it. You need to declare it inside the class, and not static:
class MyClass1 {
// other things...
string myArray[5];
};
In any case, this kind of basic question is better answered by consulting a good C++ introductory book.
If I have a user defined default constructor in my Test class, and what operations will done by using the following statement:
Test *test = new Test; //there is no () after new Test
First, does the user default constructor means "constructor without Parameters"?
for example:
class Test {
public:
Test() {
// do something here
}
}
so the new Test; means the complier will call the Test() constructor in class Test(); and perform the operations inside it, and allocate memory in heap for class Test object?
And what about the *test"? where is it ? in heap or stack? can anyone explain me?
And what about
Test test = new Test();//with () this time
what kind of constructor will be called in this case?
"Default constructor" means a constructor that can be called without parameters. It may have default parameters:
class Test {
public:
Test(int x = 42); // Still default constructor.
// Can be called as Test() and as Test(int);
};
The new operator will call operator new to allocate memory, and provided the allocation succeeds, then call one or more constructors. In this case it will call the default one to construct your object.
More than one constructor will be called if your object has a base class.
The Test* itself, test, will reside on the stack in this case.
Default constructor means the one which can be called without any parameters which includes constructors with parameters having all default values.
The statement Test *test = new Test allocates the memory for object of Test on heap and calls the default constructor for it.
Does the user default constructor means "constructor without Parameters"?
Yes, Default constructor means the constructor without any parameters. A constructor is a special & only member function for a class which has same name as the class.
The compiler generates a default constructor(constructor without any parameters) if your code needs one.
What does Test *test = new Test; do?
It allocates memory on the heap of size = size of class Test and calls the default constructor Test().
*And what about the test"? where is it ? in heap or stack? can anyone explain me?
*test is a pointer variable of the type Test on the stack which points to a dynamically allocated chunk of memory of the size of class Test on the Heap
A default constructor means a constructor that can be called without arguments. It is used to initialize the parameters of any object of a class, not necessarily pointers to objects of that class. So,
Test t;
would call the default constructor Test::Test(). Note that t is an object and not pointer to object. Some languages also have default constructors that are automatically generated when explicit constructors are not defined and over-ridden when constructors are defined.
The new operator in C++ allocates memory to the pointer from the heap and initializes it using the constructor.
HTH,
Sriram.