I'm working on some C++11 examples, but i'm a little rusty. I'm trying to add an object instance to a class attribute. I have something like this:
Entity.h
class Entity {
private:
MyClass object;
public:
Entity();
void doTest();
};
Entity.cpp
#include "Entity.h"
Entity::Entity() {
}
void Entity::doTest(stuff) {
object = new MyClass(stuff);
}
Is this correct? How can i do this in C++?
It's all correct apart from the new. Only use that when you need dynamic allocation; in this case, you just want to create an object:
object = MyClass(stuff);
Or perhaps you want to initialise it in the constructor instead:
Entity(stuff) : object(stuff) {}
It is wrong. object is an object not a pointer. but your code
object = new MyClass(stuff);
treat object as a pointer.
You can either declare object as a pointer in the class Entity or change your function doTest;
If you want a pointer it is better to use smart pointers in C++, such as unique_ptr.
In C++ your object field is really an object. That means that there is an allocated memory inside every Entity object you may create. The problem is how you can initialize that object field ?
if MyClass has no ctor or a ctor callable with no parameter, everything is ok.
if not, you should define the initialization of the field at the same time you define the ctor of Entitythis way
Entity::Entity() : object(parameters) {
code for Entities initialization
}
this is a way to ensure the correctness of your initialization so that object is initialized before you have control on the initialization of the Entity.
Your object is statically initialized inside each Entity, this is a good way, in C++, to code what is called a composition in object oriented programming.
You want to use in the decleration:
MyClass* object
Also, if you are going to use new MyClass make sure you use delete object to avoid leaks.
i.e.
Entity::Entity() { object = NULL; } //constructor
Entity::doTest(stuff) {
delete object;
object = new MyClass(stuff);
}
//Following rule of three, since we need to manage the resources properly
//you should define Copy Constructor, Copy Assignment Operator, and destructor.
Entity::Entity(const Entity& that) { //copy constructor
object = that.object;
//assumes you've correctly implemented an assignment operator overload for MyClass
}
//invoke copy and swap idiom* if you wish, I'm too lazy
Entity& Entity::operator=(const Entity& source) {
MyClass* temp = new MyClass(source.object)
//assumes you've correctly implemented an copy constructor (or default one works) for MyClass.
delete object;
object = temp;
return *this;
}
Entity::~Entity() { //destuctor
delete object;
}
You should avoid dynamic allocation if it is at all possible. You should also use smart pointers (like std::shared_ptr) but if you do wish to use raw pointers, then abide by the rule of three.
*copy and swap idiom
Related
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?
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?
I have this problem, there is a function foo() as follows,
vector<ClassA> vec;
void foo()
{
ClassA a; //inside foo, a ClassA object will be created
a._ptr = new char[10];
vec.push_back(a); //and this newly created ClassA object should be put into vec for later use
}
And AFAIK, vec will invoke ClassA's copy-ctor to make a copy of the newly created object a, and here is the problem. If I define ClassA's copy-ctor the usual way,
ClassA::ClassA(const ClassA &ra) : _ptr(0)
{
_ptr = ra._ptr;
}
then object a and its copy (created by vec) will have pointers _ptr pointing to the same area, when foo finishes, a will call the destructor to release _ptr, then a's copy in vec will be a dangling pointer, right? Due to this problem, I want to implement ClassA's copy-ctor this way,
ClassA::ClassA(ClassA &ra) : _ptr(0) //take non-const reference as parameter
{
std::swap(_ptr, a._ptr);
}
Is my implementation ok? Or any other way can help accomplish the job?
To answer your titular question: Yes, any constructor for a class T that has one mandatory argument of type T & or T const & (it may also have further, defaulted arguments) is a copy constructor. In C++11, there's also a move constructor which requires one argument of type T &&.
Having a non-constant copy constructor that actually mutates the argument gives your class very unusual semantics (usually "transfer semantics") and should be extensively documented; it also prevents you from copying something constant (obviously). The old std::auto_ptr<T> does exactly that.
If at all possible, the new C++11-style mutable rvalue references and move constructors provide a far better solution for the problem of "moving" resources around when they're no longer needed in the original object. This is because an rvalue reference is a reference to a mutable object, but it can only bind to "safe" expressions such as temporaries or things that you have explicitly cast (via std::move) and thus marked as disposable.
C++11 introduced move constructors for this exact purpose:
ClassA::ClassA(ClassA&& ra)
: _ptr(ra._ptr)
{
ra._ptr = nullptr;
}
Alternatively you can declare _ptr to be a shared pointer:
std::shared_ptr<char[]> _ptr;
and then default denerated copy constructor will do just fine.
You should not copy the pointer, you should copy the context that the pointer is pointing to. You should also initialize the class by telling it how many elements you want, instead of allocating it by accessing a public pointer.
Since you want to copy the object, not move it, you should allocate resources in the new object when copying.
class A {
int* p_;
int size_;
public:
A(int size)
: p_(new int[size]()),
size_(size) {
}
A(const A &a)
: p_(new int[a.size_]),
size_(a.size_) {
std::copy(a.p_, a.p_ + a.size_, p_);
}
...
};
int main () {
A a(10);
vec.push_back(a);
}
However, if you know that the object you will copy isn't used after it's copied, you could move it's resources instead.
The problem with your implementation is that you will not be able to pass temporary objects as arguments for this copy-ctor (temporaries are always const). Like already mentioned the best solution would be to move to c++11 and use move semantics. If it is not possible shared_array can be an alternative.
Additional comment:
Avoid these kind of problems creating the object with new and storing pointers to the object in the vector.
I want to gain a better understanding of how to implement the RAII idiom with my classes, through an example: What the recommended method is for ensuring pointers are free()'d properly in my class?
I have a class which should exist for the duration of the program. In the spirit of RAII and because I need to pass a reference to this class to other classes, I am holding it in a shared_ptr (not sure it actually needs to be held in a shared_ptr, but for fun, it is).
In the class ctor, I use 2 buffers (pointers) and then loop multiple times malloc()'ing, using the buffer and then free()'ing. The dtor should contain failsafe code to free the buffers, in the event of mishap.
The only way the dtor can see the buffers is if I declare them as class variables, however they are only used in the class ctor.
Example:
class Input
{
private:
PSOMETYPE buffer1;
public:
Input();
~Input();
}
Input::Input() : buffer1(NULL)
{
for(blahblah)
{
buffer1 = (PSOMETYPE)malloc(sizeof(SOMETYPE));
// Do work w/buffer1
if(buffer1 != NULL) { free(buffer1); buffer1 = NULL }
}
}
Input::~Input()
{
if(buffer1 != NULL) { free(buffer1); buffer1 = NULL }
}
Considering I only use the buffer in the ctor, does it make sense to declare it as a private class variable? If I declare it in the scope of the ctor, the dtor will have no knowledge as to what it is to free.
I know this is a trivial example, and honestly I could implement this as easily forgetting about using a smart pointer to reference my class and having a blank dtor, just free()'ing as I'm doing inside the loop. I have no mentor or schooling, and I'm uncertain of when the RAII idiom should be followed.
The spirit of RAII would be to use a local object to manage the locally allocated object, rather than artificially tying its lifetime to the object being constructed:
class Input
{
// no pointer at all, if it's only needed in the constructor
public:
Input();
// no explicit destructor, since there's nothing to explicitly destroy
};
Input::Input()
{
for(blahblah)
{
std::unique_ptr<SOMETYPE> buffer1(new SOMETYPE);
// or, unless SOMETYPE is huge, create a local object instead:
SOMETYPE buffer1;
// Do work w/buffer1
} // memory released automatically here
}
You should only ever have to use delete (or free, or whatever) yourself if you're writing a class whose purpose is to manage that resource - and usually there's already a standard class (such as a smart pointer or a container) that does what you want.
When you do need to write your own management class, always remember the Rule of Three: if your destructor deletes something, then the default copying behaviour of the class will almost certainly cause a double delete, so you need to declare a copy constructor and copy-assignment operator to prevent that. For example, with your class I could write the following incorrect code:
{
Input i1; // allocates a buffer, holds a pointer to it
Input i2(i1); // copies the pointer to the same buffer
} // BOOM! destroys both objects, freeing the buffer twice
The simplest way to prevent this is to delete the copy operations, so code like that will fail to compile:
class Input {
Input(Input const&) = delete; // no copy constructor
void operator=(Input) = delete; // no copy assignment
};
Older compilers may not support = delete; in which case you can get almost the same effect by declare them privately without = delete, and not implementing them.
Sorry about the title. I wasnt sure what to name it. If any mods are reading and they understand the question then please rename if needed too.
Say you create a new variable (varOne).
Inside the varOne code, other variables are created as new (varTwo, varThree).
If you call delete on varOne, will varTwo and varThree be deleted, or do you need to delete them AND delete varOne?
You only need to delete varTwo and varThree, because when you fall out of varOne's destructor, the delete you used to invoke varOne's destructor will clean up that instance of varOne.
In other words, in the example below, varOne is Foo, varTwo is m_i, and varThre is m_c:
class Foo
{
public:
Foo() : m_i( new int ), m_c( new char ) { }
~Foo() { delete m_i; delete m_c; }
// don't forget to take care of copy constructor and assignment operator here!!!
private:
int* m_i;
char* m_char;
};
main()
{
Foo* p = new Foo;
delete p;
}
Also make sure that when you do this, you follow The Rule of Three or your program will suffer memory problems. (In other words, if you are doing memory allocation in your constructor, be sure you either override or delete the default copy-constructor and assignment operators).
You have to delete them and delete varOne seperately, but actually the constructor of varOne should allocate those variables and the destructor should deallocate them if they have to be on the heap for some reason. It would be better to just store them by value and be rid of new and delete for good.
I'm not 100% sure what you mean, but in general, anything that you allocate with new, you have to individually deallocate with delete.
If you mean this in the context of a C++ class, you will need to manually delete varOne and varTwo of the destructor.
Use a smart pointer, and never ever ever delete anything in your own code.
I'm not sure how to understand your question, since you don't new a variable (all variables are static, automatic or member variables) but objects (the pointers you get from new will however usually assigned to use used to initialize variables, maybe that's what you meant?). Therefore I'll give a general answer ad hope that what you asked for is included.
First, as a basic rule, every object you allocate with new has to be deallocated explicitly with delete. However, the delete might be hidden in another object, like shared_ptr and scoped_ptr/unique_ptr from boost or C++11, or auto_ptr in earler versions of C++.
If your object contains subobjects, it's usually best to make them direct members, so you don't allocate them with new at all (indeed, that's a general rule in C++: If you don't absolutely have to dynamically allocate, don't). That is, you'd write your class as
class X
{
public:
// ...
private:
Type1 subobject1;
Type2 subobject2:
};
and don't have to mess with new/delete for the sub objects at all. However if you need to dynamically allocate the objects, you also have to delete them, e.g.
class X
{
public:
X()
{
subobject1 = new Type1();
try
{
subobject2 = new Type2();
}
catch(...)
{
delete subobject1;
}
}
~X()
{
delete subobject2;
delete subobject1;
}
// ...
private:
X(X const&); // disabled
X& operator=(X const&); // disabled
Type1* subobject1;
Type2* subobject2;
};
Note the rather complicated code in X's constructor to make sure the object is correctly cleaned up even in case of an exception. Also note that you also have to implement copy construction and assignment or disable them by making them private and unimplemented (note that C++11 offers the special syntax = delete to disable them). You can save yourself a lot of the trouble by using a smart pointer (but you still have to take care about copy construction and assignment, at least with the usual smart pointers):
class X
{
public:
X():
subobject1(new Type1()),
subobject2(new Type2())
{
}
private:
X(X const&) = delete; // disabled
X& operator=(X const&) = delete; // disabled
std::unique_ptr<Type1> subobject1;
std::unique_ptr<Type2> subobject2;
};
Here I've used C++11's unique_ptr (and consequently also used C++11 syntax for removing copy constructor and assignment operator). Note that on first impression this code seems to have no delete at all; however those deletes are actually hidden in the destructor of unique_ptr. Also note that now the explicit exception handling in the constructor is no longer needed; since the deleting is done in the destructors of the unique_ptrs, C++'s exception handling rules for constructors automatically take care of this.