Get a copy of "this" (current instance) in C++ - c++

I want to have a copy of the currently running instance.
When i change a value in the copy, original object is also affected. The copy acts as an instance.
How to avoid this? I need to create an independent copy of the calling object.
Set operator+(Set s){
Set temp = *this;
for(int i=0; s.elements[i] != '\0'; i++){
temp(s.elements[i]);
}
temp.elements[0] = 'X'; // <- this affects calling object also :(
return temp;
}

The problem is that Set temp = *this; makes a shallow copy, not a deep copy. You will have to modify the copy constructor and assignment operators for the Set class so that they make copies of all the member/contained objects.
E.g:
class Set
{
public:
Set()
{
elements = new SomeOtherObject[12];
// Could make elements a std::vector<SomeOtherObject>, instead
}
Set(const Set& other)
{
AssignFrom(other);
}
Set& operator=(const Set& other)
{
AssignFrom(other);
return *this;
}
private:
void AssignFrom(const Set& other)
{
// Make copies of entire array here, as deep as you need to.
// You could simply do a top-level deep copy, if you control all the
// other objects, and make them do top-level deep copies, as well
}
SomeOtherObject* elements;
};

Not that your function already makes two copies, since it takes its argument and returns its result per copy:
Set operator+(Set s);
So you wouldn't have to copy s, because it's already copied. I suppose this is involuntarily, so you might want to read about how to pass objects to functions and how to return objects from function in C++.
The problem you're reporting, though, hints at your copy constructor not working properly. Did you implement the copy constructor or are you using the compiler-supplied one?

This probably depends on how Set is implemented. If the assignment operator and the copy constructor haven't been overloaded to do a deep copy(including elements) then it won't work as expected.

Have you implemented a copy constructor for your class?
Default copy constructor will copy any pointer in your class, but not the content you are pointing to. You need to create a copy constructor or overload the '=' operator.

I would avoid a char pointer completely and use std::string instead. This way you dont even need a copy constructor and an assigment operator because the compiler generated once will do just fine. (because 'elements' of the 'Set' class is copy-constructible and has an assignment operator)
Here is my solution:
#include <iostream>
#include <string>
class Set{
std::string elements;
public:
Set() {
elements = "";
}
explicit Set(char* _elements) {
if (_elements)
elements = _elements;
}
Set operator+(const Set& s){
Set temp(*this);
temp.elements += s.elements;
return temp;
}
};
Btw. I added a constructor from char* so that 'elements' can somehow be initialized from outside. Not sure if this is what you wanted.

Ok. I went through rule of three and did the following changes... Can you point out what's wrong with this?
#include<iostream>
#include<cstring>
using namespace std;
class Set{
char *elements;
public:
Set() {
elements = new char('\0');
index = -1;
}
Set(const Set& cpy){
*this = cpy;
}
Set operator+(Set s){
Set temp = *this; // IMPORTANT! copy constructor of Set is called, "this" is passed as argument
// * = current OBJECT, else returns ADDRESS of current object
for(int i=0; s.elements[i] != '\0'; i++){
temp(s.elements[i]);
}
return temp;
}
Set& operator=(Set s){
delete [] elements;
elements = new char[strlen(s.elements) + 1];
strcpy(elements, s.elements); //overrides element of "this"
return *this;
}
};

Related

C++ Overloading the plus operator to add an element to an object

Constructor for object
Set<T>::Set() {
buckets = new forward_list<T>[9];
numBuck = 9;
numElem = 0;
maxLoad = 9;
}
Overloading of plus operator
Set<T>::operator+(T elem){
Set<T> res;
return res;
}
I don't quite know where to begin with this. This overloaded operator add its parameter elem to a copy of *this and return the result.
ex:
Set<char>setA;
Set<char>setB;
setA.Add('a')
setA.Add('b')
setA.Add('c')
// setA contains {'a','b','c'}
setB = setA + 'd'
// setB should now contain {'a','b','c','d'}
Any guidance?
edit: Clarified operator overload functionality
You can just make a copy function in the set, and use the Add function inside the overload. Demo code:
Set<T>::operator+(T elem)
{
Set<T> result;
result.Copy(*this);
result.Add(elem);
return result;
}
NOTE: Or you can follow #jxh's answer and use the default copy constructor. I would make a Copy function just to be explicit. :)
For the copy of *this, you can modify the definition of res to use the copy constructor.
Set<T> res(*this);
Adding the elem argument uses the same method you used for adding elements to setA.
res.Add(elem);
Since it looks like your code is managing a pointer, you will need to define your own destructor, to release the allocated memory.
Set<T>::~Set() {
delete[] buckets;
}
You are also obligated to implement your own copy constructor and assignment operator, due to the Rule of Three. Your copy constructor would need to performs its own allocation, and the elements from the other Set need to be copied over.
Set<T>::Set(const Set<T> &other) {
numBuck = other.numBuck;
numElem = other.numElem;
maxLoad = other.maxLoad;
buckets = new forwardList<T>[numBuck];
// ... add code to copy elements from other.buckets
}
The assignment operator can be implemented using the copy-swap idiom.
Set<T> & Set<T>::operator = (Set<T> other) {
using std::swap;
swap(*this, other);
return *this;
}
To avoid needing to implement your own destructor / copy constructor / assignment operator methods, you can opt to represent your buckets with a vector rather than managing your own pointer.
std::vector<forward_list<T>> buckets;

C++assingment operator using destructor and copying constructor

I was working on a class with multiple dynamic fields and I was looking for quick way of coding assignment operator.
So let's say I have some basic class Cla, which stores dynamic array of integers (arr) and the size of said array (n).
I've coded this:
Cla::Cla(int* arr, int n) : n(n)
{
this->arr = new int[n];
//allocation error handling
while (--n >= 0)
this->arr[n] = arr[n];
}
Cla::~Cla()
{
delete[] arr;
}
Cla::Cla(const Cla& copy) : Cla(copy.arr, copy.n){}
Cla& Cla::operator= (const Cla& asg)
{
this->~Cla();
*this = asg;
return *this;
}
All of it works properly, except for operator=. The idea was that I'll just destroy my object and then create it again with copying constructor (for the sake of simplicity of the example I don't consider the situation where both objects have the same size and there is no need for deallocation and new allocation). It compiles, but it gives me some nasty errors when executed.
Can you give me some advice on how to correct this code? Is this even possible for it to work this way?
(I know how to write an assingment operator, I'm just asking whether it is possible to do it using destructor and copying constructor. I couldn't find anything like that on the internet.)
Your operator= has undefined behavior. First, you cannot manually call a destructor on an object that was not allocated with placement-new. Second, once an object is destroyed, it cannot be used anymore, which means *this = asg is accessing invalid memory once this->~Cla() has been called, as this is no longer pointing at a valid object. Third, your operator= is running an endless recursion loop, calling itself over and over until the call stack blows up (if you are lucky).
Since you want to use your copy constructor, your operator= would be better served by using the copy-swap idiom instead. Construct a local object to make use of your copy constructor, and then swap the contents of that object with this so that this takes ownership of the copied data and the local object frees the old data when it goes out of scope, eg:
Cla& Cla::operator= (const Cla& asg)
{
if (&asg != this)
{
Cla temp(asg);
std::swap(arr, temp.arr);
std::swap(n, temp.n);
}
return *this;
}
Alternatively:
void Cla::swap(Cla &other)
{
std::swap(arr, other.arr);
std::swap(n, other.n);
}
Cla& Cla::operator= (const Cla& asg)
{
if (&asg != this) {
Cla(asg).swap(*this);
}
return *this;
}
That being said, the fact that your copy constructor is delegating to your converting constructor means that you are using C++11 or later, in which case you should also implement move semantics into your class, not just copy semantics, eg:
Cla::Cla() : arr(nullptr), n(0)
{
}
Cla::Cla(int* arr, int n) : arr(new int[n]), n(n)
{
while (--n >= 0)
this->arr[n] = arr[n];
}
Cla::Cla(Cla &&c) : arr(nullptr), n(0)
{
c.swap(*this);
}
Cla::Cla(const Cla& c) : Cla(c.arr, c.n)
{
}
Cla::~Cla()
{
delete[] arr;
}
void Cla::swap(Cla &other)
{
std::swap(arr, other.arr);
std::swap(n, other.n);
}
Cla& Cla::operator= (Cla asg)
{
asg.swap(*this);
return *this;
}
By passing the asg parameter by value, operator= can decide whether to use copy semantics or move semantics at the call site based on whether an lvalue or rvalue is being passed to it. The compiler will pick the appropriate constructor to construct the asg parameter with, and then this can take ownership of the resulting data.

How to return dynamic structure without pointer?

I have to overload '+' operator for two dynamic containers.
Occurance Occurance::operator +(const Occurance& occ) const {
Occurance* result = new Occurance;
Iterator i1(head);
Iterator i2(occ.head);
while( !(i1.isNULL() && i2.isNULL()) ) {
if(i1.getCount() >= i2.getCount()) {
result->add(i1.getFile());
result->tail->count = i1.getCount();
++i1;
}
else {
result->add(i2.getFile());
result->tail->count = i2.getCount();
++i2;
}
}
return *result;
}
When I do:
Occurance occ = occ1+occ2;
Pointers to the begin of the list are copied correctly and everything works fine but I'm losing reference to result. When occ destructor is called whole list is destroyed, but not the first element of result as I have simply copied it's content instead of reference.
When I change return type to reference the same occurs but during assignment.
Another idea is to not create the 'result' dynamically, so it's automaticly destroyed at the end of function, but then it's calling the destructor which is destroying whole list.
Is there any simple and "proper" way to create such structure and return it without this memory leak? And of course the returned type must be the object or reference as it is expected from '+' operator.
I have figured out a nasty hack involving changing pointer to function in the destructor, but maybe I'm just missing something very simple?
Edit:
Of course class follows the rule of three. Here is assignment:
Occurance& Occurance::operator =(const Occurance& occ) {
destruct();
head = occ.head;
current = occ.current;
tail = occ.tail;
return *this;
}
Occurance::Occurance(const Occurance& occ) {
head = occ.head;
current = occ.current;
tail = occ.tail;
}
Occurance::~Occurance() {
destruct();
}
destruct just destroys the list that starts at 'head'.
The class declaration:
class Occurance {
private:
class Node {
public:
Node* next;
Node* prev;
int count;
const File* file;
Node(const File& a_file, Node* a_prev);
};
Node* head;
Node* tail;
Node* current;
void destruct();
public:
class Iterator {
private:
Node* node;
public:
Iterator();
Iterator(Node* a_node);
void operator ++();
const File& getFile();
int getCount();
bool isNULL();
};
Occurance();
Occurance(const Occurance& occ);
void add(const File& a_file);
Occurance& operator =(const Occurance& occ);
Occurance operator +(const Occurance& occ) const; //dodaje listy zachowując sortowanie
Iterator begin() const;
virtual ~Occurance();
};
Your copy constructor and assignment operator are broken. You either need to do a deep copy of your list, or you need to implement some kind of sharing semantics (e.g. reference counting). You appear to have a linked list, and you are simply copying the head and tail pointers. So when you make a copy, and one is destroyed, it destroys the other one's list too.
I assume your default constructor and/or your add function does some dynamic allocation of nodes. Then your copy constructor and assignment operator need to dynamically allocate nodes too, which are completely independent of the nodes of the object which is being copied. If C++11 is available to you, you should also consider implementing a move constructor, and a move assignment operator.
Once those functions are all correct, your operator+ should look something like this:
Occurance Occurance::operator +(const Occurance& occ) const {
Occurance result; // no dynamic allocation
// operate on result
return result;
}
Another idea is to not create the 'result' dynamically, so it's automaticly destroyed at the end of function, but then it's calling the destructor which is destroying whole list.
You should read about copy constructor. Before the returning object's destructor is called, the copy constructor is called that copies the data from that object to the temporary object that will hold the result of occ1+occ2 operation. I assume you have members that point to dynamically allocated data and in this case, when the copy constructor is called, it assigns the pointer to the temp object instead of allocate new memory and copy data. You must code it on your own. I'd advise you to read: http://www.cplusplus.com/articles/y8hv0pDG/
Also note that you should overload operator = in the same manner if you want to perform this assignment
occ = occ1+occ2
edit: Sorry, I can't comment, could you also copy your class declaration?
In C++, the general principle is to return copies on the stack, not objects allocated on the heap. So in this case you would simply do:
Occurance Occurance::operator +(const Occurance& occ) const
{
Occurance result;
// do whatever
return result;
}
and call it:
Occurance occ = occ1+occ2;
The compiler is smart enough to understand not to make a copy but to re-use the object that you're returning into (this is called return-value optimisation or RVO).
If you really need the object to be the exact same object created inside your function for whatever reason, then you can either: return a smart pointer (look up shared_ptr) or use the new C++11 move operator.

Deep copy into block of c-array on heap

Consider for example a template container class that holds a buffer that is allocated on the heap:
T *_buffer = new T[SIZE]
Just a simple pointer to c array of type T.
This class is templated. However I am having issues with performing a deep copy of an object into my buffer.
In my unit test, i set up a test class:
class test
{
public:
int* _ptrInt;
test() {_ptrInt = nullptr;}
test(const int i)
{
_ptrInt = new int;
*_ptrInt = i;
}
test(const test& other)
{
_ptrInt = new int;
*_ptrInt = *other._ptrInt;
}
~test()
{
delete _ptrInt;
}
};
on my container I call set, passing a temporary as the data:
container.set(0, test(5));
// destructor called on copy immediately after statement, invalidating deep copy in buffer
void set (const int& index, const T& data)
{
int i = realign(index);
T copy = data;
_buffer[i==SIZE?i-1:i] = copy; // ternary statement and index work
}
however, _buffer takes copy as a reference, the moment copy goes out of scope, it deletes the same pointer that is held in the _buffer. I am trying to force the _buffer to assign by value. But I have had no luck.
memcpy still copies the pointers to point to the same address
test copy constructor is correctly called
move semantics would require class to have move constructor
std::vector somehow implements this to copy correctly, whether its T/T*, heap/stack, with/without move constructor, so I know it must be possible
Is there a way I can assign by value to the _buffer on the heap?
You are "assigning by value." However, your test class doesn't implement the assignment operator operator=, so the assignment invokes the compiler-generated default assignment operator which simply copies member-by-member. Hence the problems with shallow assignment.
Also, your copy constructor will explode if other._ptrInt is nullptr.

The efficient way to write move copy and move assignment constructors

Are the following assignment and copy move constructors the most efficient?
if anybody have other way please tell me?
I mean what bout std::swap? and calling assignment through copy constructor is safe in the code below?
#include <iostream>
#include <functional>
#include <algorithm>
#include <utility>
using std::cout;
using std::cin;
using std::endl;
using std::bind;
class Widget
{
public:
Widget(int length)
:length_(length),
data_(new int[length])
{
cout<<__FUNCTION__<<"("<<length<<")"<<endl;
}
~Widget()
{
cout<<endl<<__FUNCTION__<<"()"<<endl;
if (data_)
{
cout<<"deleting source"<<endl;
}
else
{
cout<<"deleting Moved object"<<endl;
}
cout<<endl<<endl;
}
Widget(const Widget& other)
:length_(other.length_),
data_(new int[length_])
{
cout<<__FUNCTION__<<"(const Widget& other)"<<endl;
std::copy(other.data_,other.data_ + length_,data_);
}
Widget(Widget&& other)
/*
:length_(other.length_),
data_(new int[length_])*/
{
cout<<__FUNCTION__<<"(Widget&& other)"<<endl;
length_ = 0;
data_ = nullptr;
std::swap(length_,other.length_);
std::swap(data_,other.data_);
}
Widget& operator = (Widget&& other)
{
cout<<__FUNCTION__<<"(Widget&& other)"<<endl;
std::swap(length_,other.length_);
std::swap(data_,other.data_);
return *this;
}
Widget& operator = (const Widget& other)
{
cout<<__FUNCTION__<<"(const Widget& other)"<<endl;
Widget tem(other);
std::swap(length_,tem.length_);
std::swap(data_,tem.data_);
return *this;
}
int length()
{
return length_;
}
private:
int length_;
int* data_;
};
int main()
{
{
Widget w1(1);
Widget w2(std::move(Widget(2)));
w1 = std::move(w2);
}
cout<<"ENTER"<<endl;
cin.get();
return 0;
}
Looks fine from an efficiency POV, but contains an awful lot of duplicated code. I'd
Implement a swap() operator for your class.
Initialize length_ and data_ where they are declared.
Implement operations in terms of other operations whereever possible.
You might want to use std::memcpy instead of std::copy since you're dealing with a raw array anyway. Some compilers will do that for you, but probably not all of them...
Here's a de-duplicated version of your code. Note how there is only one place which needs to know how two instances of Widget are swapped. And only one place which knows how to allocate a Widget of a given size.
Edit: You usually also want to use argument-dependent lookup to locate swap, just in case you ever have non-primitive members.
Edit: Integrated #Philipp's suggestion of making the assignment operator take it's argument by value. That way, it acts as both move assignment and copy assignment operator. In the move case, not that if you pass a temporary, it won't be copied, since the move constructor, not the copy constructor will be used to pass the argument.
Edit: C++11 allows non-cost members to be called on rvalues for compatibility with previous versions of the standard. This allows weird code like Widget(...) = someWidget to compile. Making operator= require an lvalue for this by putting & after the declaration prevents that. Note though that the code is correct even without that restriction, but it nevertheless seems like a good idea, so I added it.
Edit: As Guillaume Papin pointed out, the destructor should use delete[] instead of plain delete. The C++ standard mandates that memory allocated via new [] be deleted via delete [], i.e. it allows new' andnew []` to use different heaps.
class Widget
{
public:
Widget(int length)
:length_(length)
,data_(new int[length])
{}
~Widget()
{
delete[] data_;
}
Widget(const Widget& other)
:Widget(other.length_)
{
std::copy(other.data_, other.data_ + length_, data_);
}
Widget(Widget&& other)
{
swap(*this, other);
}
Widget& operator= (Widget other) &
{
swap(*this, other);
return *this;
}
int length() const
{
return length_;
}
private:
friend void swap(Widget& a, Widget& b);
int length_ = 0;
int* data_ = nullptr;
};
void swap(Widget& a, Widget& b) {
using std::swap;
swap(a.length_, b.length_);
swap(a.data_, b.data_);
}
The answer is in response to #Abdulrhman's complaint in the comments above that things fail for some (obscure) sequences of assignments. Put into a seperate answer because it's more readable that way.
The complaint was that
Widget w(2);
w = Widget(1) = std::move(w);
crashes. Here's the output I get from
Widget w(2);
w.data()[0] = 0xDEAD; w.data()[1] = 0xBEEF;
w = Widget(1) = std::move(w);
std::cerr << std::hex << w.data()[0] << w.data()[1] << std::endl;
with some code added to Widget to log constructor, destructor and assignment operator calls. Interleaves are comments about where those calls come from
w is constructed
0x7fff619c36c0: [constructor] allocated 2#0x1043dff80
temporary Widget(1) is constructed
0x7fff619c37c0: [constructor] allocated 1#0x1043e0180
first (right) assignment operator argument is constructed. w is empty afterwards!
0x7fff619c3800: [default constructor] empty
0x7fff619c3800: [move constructor] stealing 2#0x1043dff80 from 0x7fff619c36c0, replacing with 0#0x0
first assignment operator does it's job, i.e. moves from by-value argument.
0x7fff619c37c0: [assignment] stealing 2#0x1043dff80 from 0x7fff619c3800, replacing with 1#0x1043e0180
second (left) assignment operator arguments is constructed
0x7fff619c3780: [constructor] allocated 2#0x1043e0280
0x7fff619c3780: [copy constructor] copying 2#0x1043dff80 from 0x7fff619c37c0
second assignment operator does it's job, i.e. moves from by-value argument
0x7fff619c36c0: [assignment] stealing 2#0x1043e0280 from 0x7fff619c3780, replacing with 0#0x0
second assingment operator's by-value argument is destructed
0x7fff619c3780: [destructor] deleting 0#0x0
first assignment operator's by-value argument is destructed
0x7fff619c3800: [destructor] deleting 1#0x1043e0180
temporary created as Widget(1) is destructed.
0x7fff619c37c0: [destructor] deleting 2#0x1043dff80
data contains in "w" after assignments.
deadbeef
finally, "w" is destructed.
0x7fff619c36c0: [destructor] deleting 2#0x1043e0280
I can see no problem there, and compiling this with clang and -faddress-sanitizer, -fcatch-undefined-behaviour doesn't complain either.
Note, though, that the second assigment (the left = operator) copies instead of moving. This is because the first (right) assignment operator returns an lvalue-reference.
You don't need so many swaps and assignments in your move constructor. This:
Widget(Widget&& other) :
length( other.length_ ), data( other.data_ )
{
other.length_ = 0;
other.data_ = nullptr;
}
does the minimum work for the move constructor: 4 assignments in total. Your version had 8, counting the ones in the calls to swap().
Your move assignment is OK, but you might want to consider just writing one operator=() to cover both cases:
Widget &operator=( Widget other ) {
delete data_;
data_ = other.data_;
other.data_ = nullptr;
length_ = other.length_;
other.length_ = 0;
return *this;
}
This is slightly less efficient than your version, in that it can move twice.