Is it possible to make a local copy of 'this' pointer in a class function? The purpose is to then modify the copy and return it, without modifying 'this' itself.
The function looks like this:
classA classA::function() {
classA newObject = //where I need help;
//modification of newObject
return newObject;
}
You can create copies from this as long your class provides a copy constructor by simply dereferencing the this pointer as needed:
classA classA::function() {
return *this;
// ^^^^^ Simply dereference and let the compiler do the copying
}
Ensure your class declaration follows the Rule of 3/5/zero!
Related
So say I was using this to create an object:
MyClass myObject;
and I had the function inside of the class to act upon the object. So one way could be using parameters, like this:
MyClass foo(MyClass a) {
return a;
}
Seems simple. But is there a way so I can use myObject.foo() and it would still return a even though I'm not using it as a parameter? One example could be some of the methods in std::string - you can use std::string.swap(), using the object for the swap() function.
Is there a way, or am I being stupid?
First off, keep in mind that you original code of
MyClass foo(MyClass a) {
return a;
}
does not actually return a. It returns a copy of a, which itself is a copy of whatever instance of MyClass you passed into foo. If you want to pass in a given object, act on it and return it, you need to use references, like so
MyClass & foo(MyClass & a) {
return a;
}
This will ensure that the a you get back from a call to foo is the exact same object you passed into it.
Additionally, an object can always return a reference to itself in one of its members...
class MyClass {
MyClass & foo() { return *this; }
}
This is especially useful in classes where you might want to chain a large number of operations together...
MyClass my = MyClass().foo().bar("Hello").baz(5);
Inside every member function is a magic secret parameter, which is a pointer to the object who's method was called, and the parameter's name is this.
MyClass& foo() { //returns reference to existing MyClass instead of making copies
this->print(); //call a different member
return *this; //return a reference to itself. Common for `operator=` and such.
}
Inside a class's (non-static) member function, you can use *this to name the object the function was called on.
So:
MyClass MyClass::foo() {
return *this;
}
(Notice that function returns a copy of the object. If you don't want a copy, use a reference as in #Jherico's answer.)
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
Is it possible to use the this pointer to assign the data from a calling object to one declared in a const member function? Something like:
(assuming I've already built SomeClass)
void func() const
{
SomeClass object1;
object1 = *this;
}
int main()
{
SomeClass object2;
object2.func();
return 0;
}
I know the above function is pointless. I'm just wondering if it's a legal assignment using *this.
This code is fine, so long as SomeClass has a copy assignment operator. The const on the member function declares that you will not change the state of the object: func() doesn't do this, so it is legal code. There are ways of subverting const if you try hard enough, however, this is not one of them.
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 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.