Get lost in parameter passing by reference, by value - c++

I am trying to make a bag container. The problem that beyond me occurs when I am overloading the = operator.
Zsak& Zsak::operator =(const Zsak& a)
{
(*this).V=a.V;
(*this).elemsz=a.elemsz;
return *this;
}
with this header:
class Zsak
{
public:
Zsak (){V=new Elem[100];}
Zsak (const Zsak & a)
{
*this=a;
}
Zsak(int meret)
{
V=new Elem[meret];
}
~Zsak(){delete[] V;}
Zsak& operator -(const Zsak& b);
Zsak& operator =(const Zsak& a);
void Zsak_Ba(int e);
void Zsak_Bol(int e);
bool Uress();
int E_Hany(int e) const;
friend std::ostream& operator << (std::ostream& out,const Zsak& z);
private:
Elem *V;
int elemsz=0;
};
The Zsak_Ba puts an element into the bag;
The Zsak_Bol draws out an element from the bag;
What I observed through testing is that the address of const Zsak a identify with the address of *this .
with this context
Zsak z(5),c(5);
z.Zsak_Ba(1);
z.Zsak_Ba(1);
z.Zsak_Ba(1);
z.Zsak_Ba(2);
z.Zsak_Ba(2);
z.Zsak_Ba(2);
z.Zsak_Ba(4);
Zsak d=z;
d.Zsak_Bol(1);
cout<<z<<endl<<d;
It prints :
1 2
2 3
4 1
1 2
2 3
4 1
And what it really should print is:
1 3
2 3
4 1
1 2
2 3
4 1
What i should do to obtain this?
What i am doing wrong? And why?
Thanks a lot!

You are only copy the pointers (and not the content) in you assignment operator.
Zsak& Zsak::operator =(const Zsak& a)
{
if (this == &a) { // or std::addressof(a)
return *this;
}
delete[] V;
elemsz=a.elemsz;
V=new Elem[elemsz];
for (std::size_t i = 0; i < elemsz; ++i) {
V[i] = a.V[i];
}
return *this;
}
Additionally, I don't see where the elemsz is being updated (outside the member initialisation). I would imagine it would be in constructors.
Zsak(int meret)
{
V=new Elem[meret];
elemsz = meret;
}
And
Zsak ()
{
V=new Elem[100];
elemsz = 100;
}
It may also be worth noting that often a "copy-swap" is used to implement the assignment operator, and a full copy in the copy constructor (basically the other way around from what you have it).
The "copy-swap" would look like
Zsak (const Zsak & a) : elemsz(a.elemsz)
{
V = new Elem[elemsz];
for (int i = 0; i < elemsz; ++i) { // copy the contents
V[i] = a.V[i];
}
}
Zsak& Zsak::operator =(const Zsak& a)
{
Zsak temp(a);
std::swap(this->elemsz, temp.elemsz);
std::swap(this->V, temp.V);
return *this;
}
It incurs some overhead with on assignment to self, a test for self assignment can be added for this if needed.
Understanding that this is a task to use and implement dynamic memory, it may be best to re-factor out the Elem array and its management outside the of the main class. It is generally easier to maintain and correct bugs and issues as they arise.

If you use vector<Elem> instead of manual dynamic memory, you do not need any user-defined copy constructor or assignment operator. It will just work. This is the preferred solution. Let C++ do the work for you.

Related

Need working syntax for vector in class in this c++ .h-file

I can´t get the code to be vieved here for some unknown reason so I post my code with JavaScript snippets. Can anybody help me straighten this code out? I really need it to work and I am stuck. How can I write it so it works? I did put my code into JavaScript snippets but it´s not working. It is C++ code and i need a vector in a class.
class Bank {
public:
Bank(int m_size): konton(m_size, 0) {}
unsigned int getSize() const { return konton.size(); }
Bank(const Bank& _konton,) : konton(_konton){}
Bank(const Bank &rhs) : konton(rhs.konton) {}
Bank operator=(const Bank &rhs)
{
if (&rhs == this)
{
return *this;
}
konton = rhs.konton;
return *this;
}
void SetInfo(const int _konton)
{
konton = _konton;
}
int Konton() const { return konton; }
private:
vector<Bank> konton;
};
#endif
I cleaned a bit your mess and changed a bit metods, hope you gonna understand. But first of all take a look at rule of three/five/zero, because this code is mostly about it. Down below I pointed out some important things. It's not perfect, but should be got place to start.
class Bank {
public:
//
// Default constructor
// You don't need to define size of vector
Bank(): konton() {}
// Copy constructor
Bank(const Bank& other)
: konton(vector<int> (other.konton)) {
}
// Copy assignment operator
Bank operator=(const Bank &rhs)
{
if (&rhs == this) return *this;
konton = rhs.konton;
return *this;
}
// You missing destructor ~Bank();
//
// Also you can add two more functions:
// - Move constructor Bank(const Bank&& other);
// - Move assignment operator Bank& operator=(Bank&& other);
// This just add new element at the end of konton
void addKonto(const int _konto)
{
konton.push_back(_konto);
}
// And this remove last
void removeKonto()
{
konton.pop_back();
}
// Getters
vector<int> getKonton() const { return konton; }
unsigned int getSize() const { return konton.size(); }
private:
// I guess you mean to store accounts numbers in the Bank class
// To make it simple I made it int but, it can by any other your specific data type
vector<int> konton;
};
PS. Consider using IDE with on-the-fly syntax checking.
Edit: Here you have some more about this.

Copy Constructor (Deep Copy) c++

I am working on an assignment that calls for the writing the function implementations of the Big 3 when constructing a class with pointers. I seem to be having trouble with the copy constructor. I think I am doing the other 2 correctly.
class RealBox
{
private:
float* m_reals; // Array of Real Numbers
int m_boxsize; // number of Real Numbers in this box
public:
// Purpose: Constructs an Real-Box
// Preconditions:
// 's' is greater than 0;
// Postconditions:
// m_reals points to a dynamically allocated array of size 's'
// all elements of m_reals[] are initiallized to 'a'.
RealBox(int s, float a);
/*
* --------- Big 3 Member Functions -----------
*/
// Purpose: Destructor
// Postconditions: m_reals[] deallocated
~RealBox();
// Purpose: Operator=, performs a deep copy of 'rhs' into 'this' RealBox
// Parameters: rhs, RealBox to be copied
// Returns: *this
// Postconditions: *this == rhs
const RealBox& operator=(const RealBox& rhs);
// Purpose: Copy Constructor
// Parameters: rhs - RealBox to be copied
// Postconditions: *this == rhs
RealBox(const RealBox& rhs);
/*
* ----- Simple Accessor Operations -----
*/
// Purpose: Sets a value in the RealBox
// Parameters: 'i' location to set
// 'x' value to store
// PreConditions: 'i' is between the boundaries of the RealBox
// Postconditions: element 'i' in the RealBox is set to 'x'
void set( int i, float x);
/*
* ----- Complex Accessor Operations -----
*/
// Purpose: prints the RealBox
friend std::ostream& operator<< (std::ostream& out,
const RealBox& box);
}; // RealBox
#include "realbox.h"
#include <iostream>
using namespace std;
RealBox::RealBox(int s, float a)
{
m_reals = new float[s];
for (int i=0; i < s; i++)
{
m_reals[i] = a;
}
}
RealBox::~RealBox()
{
delete [] m_reals;
m_reals = NULL;
}
const RealBox& RealBox::operator =(const RealBox& rhs)
{
if(this != &rhs)
*this = rhs;
return(*this);
}
RealBox::RealBox(const RealBox& rhs)
{
m_reals = new float[m_boxsize];
*this = rhs.m_reals;
}
void RealBox::set(int i, float x)
{
m_reals[i] = x;
}
std::ostream& operator<< (std::ostream& out, const RealBox& box)
{
out <<"[ ";
for (int i = 0; i < box.m_boxsize; i++)
{
out << box.m_reals[i] << ", ";
}
out <<"]"<< endl;
return(out);
}
When I try to compile, I am getting the error:
realbox.cpp: In copy constructor ‘RealBox::RealBox(const RealBox&)’:
realbox.cpp:33:8: error: no match for ‘operator=’ (operand types are ‘RealBox’ and ‘float* const’)
*this = rhs.m_reals;
^
realbox.cpp:33:8: note: candidate is:
realbox.cpp:23:16: note: const RealBox& RealBox::operator=(const RealBox&)
const RealBox& RealBox::operator =(const RealBox& rhs)
^
realbox.cpp:23:16: note: no known conversion for argument 1 from ‘float* const’ to ‘const RealBox&’
I think my operator = overload is faulty as well but I'm not sure exactly what went wrong. It didn't give me that error until I started trying to fix. It's trying to say I'm comparing two different data types but I'm not sure how that is happening.
This line:
*this = rhs.m_reals;
Attempts to assign a float* to a RealBox object. The two types are incompatible.
Second, you failed to initialize m_boxsize when you constructed the object.
What you want to do is this:
RealBox::RealBox(const RealBox& rhs)
{
m_boxsize = rhs.boxsize;
m_reals = new float[m_boxsize];
for (int i = 0; i < m_boxsize; ++i )
m_reals[i] = rhs.m_reals[i];
}
This can be shortened to this:
RealBox::RealBox(const RealBox& rhs) : m_boxsize(rhs.m_boxsize),
m_reals(new float[rhs.m_boxsize])
{
std::copy(rhs.m_boxsize, rhs.m_boxsize + m_boxsize, m_reals);
}
In addition, your other constructor needs to initialize the m_boxsize variable:
RealBox::RealBox(int s, float a) : m_boxsize(s)
{
m_reals = new float[s];
for (int i=0; i < s; i++)
m_reals[i] = a;
}
This can also be shortened to this:
RealBox::RealBox(int s, float a) : m_boxsize(s), m_reals(new float[s])
{
std::fill( m_reals, m_reals + s, a);
}
The std::fill and std::copy are defined in the <algorithm> header.
Once you fix this, the assignment operator is very simple:
#include <algorithm>
//...
RealBox& RealBox::operator =(RealBox rhs)
{
std::swap(rhs.m_reals, m_reals);
std::swap(rhs.m_boxsize, m_boxsize);
return *this;
}
Usage of the copy/swap idiom makes this all possible. Simple as simple can be.
What is the copy-and-swap idiom?
sorry for short answer ...
first add a member to save the table size inside the costructor
RealBox::RealBox(int s, float a)
{
m_reals = new float[s];
for (int i=0; i < s; i++)
{
m_reals[i] = a;
}
m_realCount = s;
}
then replace :
RealBox::RealBox(const RealBox& rhs)
{
m_reals = new float[m_boxsize];
*this = rhs.m_reals; // << this is a big mistake
}
by :
RealBox::RealBox(const RealBox& rhs)
{
this->m_reals = new float[rhs.m_realCount];
memcpy(this->m_reals,rhs.m_reals,rhs.m_realCount*sizeof(float));
this->m_realCount = rhs.m_realCount;
}
You may need to include stdlib.h

Operator overloading "equal to"

I want to overload equal to "=" operator in C++ for
class Array
{
int *p;
int len;
};
All functions/constructor etc. are defined.
My question:
Could someone give me the prototype of the operator overloaded function?
And suppose:
Array a,b;
b=a;
Which of "a" and "b" would be passed implicitly and which explicitly?
Thanks in advance.
The prototype is Array& operator=(const Array& that).
While implementing this, remember about the rule of three and make good use of the copy-and-swap idiom.
You're looking for the assignment operator = (not equal-to, which is operator== and usually serves as an equality comparison)
class Array
{
int *p;
int len;
public:
// Assignment operator, remember that there's an implicit 'this' parameter
Array& operator=(const Array& array)
{
// Do whatever you want
std::cout << "assignment called";
return *this;
}
};
int main(void) {
Array a, b;
a = b;
}
remember that since you wrote "All functions/constructor etc. are defined" you should pay attention to what you need your class to do and possibly also implement destructor as in the rule of three (and/or take a look at its variants in C++11, might be relevant since there's no other code posted).
There is probably more than one way to do it, but here is an option.
Public Functions:
Array::Array(const Array& array)
{
Allocate(0);
*this = array;
}
Array::~Array()
{
Deallocate();
}
const Array& Array::operator=(const Array& array)
{
if (this == &array)
return *this;
Deallocate();
Allocate(array.len);
for (int i=0; i<len; i++)
p[i] = array.p[i];
return *this;
}
Non-Public Functions:
void Array::Allocate(int size)
{
len = size;
if (len > 0)
p = new int[len];
}
void Array::Deallocate()
{
if (len > 0)
delete[] p;
len = 0;
}
Of course, you can always use a vector<int> instead...

Trying to reduce memory allocations, what are the tricks to overloading operators?

I have written out my class with overloaded operators but I am trying to reduce the amount of memory allocations (as shown by valgrind on Linux). I understand that in certain instances that the copy constructor is called to make a local copy of an object for the function but I'm unsure which situations. As it stands I'm making a new object in each case so I feel that I could get away with ridding some of the "new" calls if I were to make use of the already copied pieces. Below are my operator+ and operator+= for reference.
// ---------------------------------------------------------------------------
// operator+
// Adds two Poly objects
Poly Poly::operator+(const Poly& rhs) const {
//case where rhs has more terms
if (maxExponent < rhs.maxExponent) {
Poly temp(rhs);
for (int i = 0; i <= maxExponent; i++) {
temp.polynomial[i] += polynomial[i];
}
return temp;
}
else {
Poly temp(*this);
for (int i = 0; i <= rhs.maxExponent; i++) {
temp.polynomial[i] += rhs.polynomial[i];
}
return temp;
}
}
// ---------------------------------------------------------------------------
// operator+=
// Adds and assigns two Poly objects
Poly& Poly::operator+=(const Poly& rhs) {
*this = *this + rhs;
return *this;
}
Here is my operator= in case the tricks depend on this:
// ---------------------------------------------------------------------------
// operator=
// Assigns a Poly object to another
const Poly& Poly::operator=(const Poly& other) {
if (&other != this) {
delete[] polynomial;
maxExponent = other.maxExponent;
polynomial = new int[maxExponent + 1];
for (int i = 0; i <= maxExponent; i++) {
polynomial[i] = other.polynomial[i];
}
}
return *this;
}
The technique you are looking for is called "expression templates".
Your operator+ takes two Poly& objects, and returns a should_be_added< Poly&, Poly& >. If you add again, it returns a should_be_added< should_be_added<Poly&, Poly&>, Poly& > (or possibly should_be_added< Poly&, Poly&, Poly& > if you know things commute and you prefer things to be flat, but that is extra work).
should_be_added then has a conversion-to-Poly, or Poly has an implicit should_be_added< T, U >&& constructor (with efficient move these two are equivalent). At that point, you have at compile time the complete tree of expressions you are assigning to your Poly. With lots of work and care, you can efficiently build a single output value.
A good way to start is to start with your operator+=(Poly const& o) and operator+=(Poly&& o) and similar "mutating" operators. These primitives can make writing other operators efficiently much easier.
You probably want to write a custom Poly& operator=( should_be_added<T,U>&& src ) so that it reuses any memory in the existing Poly object. An easy way to do this is to have a method in should_be_added that says Poly result( Poly&& src ), and implement operator Poly() as operator Poly() const { return result( Poly{} ); }, and the operator= is { swap( *this, src.result(std::move(*this)) ); return *this }
Now, none of this is easy -- expression templates are medium-deep template-fu. But the result can be that you can do your mathematical expressions in a natural way, and lose next to nothing.
Note that efficient move semantics should be easy for your Poly class -- just move the internal buffer and clear the source one.
My solution would be to reimplement Poly class with following idea: let's make it impossible to modify field 'polynomials' and make it shared across copies of same Poly using shared_ptr. This way we can have O(1) copy operator while operator+ is still O(n) - with possibility of O(1) in optimistic case :)
Let's also use std::vector instead of table and be careful about our public interface. In return we get:
smaller memory consumption
no code duplication
no need to implement copy constructor; default will work just fine :)
Forgive my sloppy implementation of operator<<. I left out implementation of optimistic case for operator+ as an exercise to the reader :).
Implemented using c++11, because I am not a masochist.
#include <memory>
#include <vector>
#include <initializer_list>
#include <iostream>
class Poly {
public:
Poly() : polynomial_(NULL) {}
Poly(std::initializer_list<double> il)
{
polynomial_.reset(new std::vector<double>(il.begin(), il.end()));
}
unsigned max_exp() const
{
return polynomial_ ? polynomial_->size() : 0;
}
Poly operator+(const Poly& o) const
{
const bool has_bigger_exp = max_exp() > o.max_exp();
const Poly & poly_big = has_bigger_exp ? *this : o;
const Poly & poly_small = has_bigger_exp ? o : *this;
auto * tmp = new std::vector<double>(*poly_big.polynomial_);
for (unsigned i = 0; i < poly_small.max_exp(); ++i) {
tmp->at(i) += poly_small.polynomial_->at(i);
}
Poly ret_obj;
ret_obj.polynomial_.reset(tmp);
return ret_obj;
}
Poly& operator+=(const Poly& o)
{
*this = *this + o;
return *this;
}
private:
std::shared_ptr<const std::vector<double>> polynomial_;
friend std::ostream& operator<<(std::ostream& os, const Poly& obj);
};
std::ostream& operator<<(std::ostream& os, const Poly& obj)
{
if (obj.max_exp() == 0) {
os << "0" << std::endl;
return os;
}
for (unsigned i = obj.max_exp()-1; i > 0; --i) {
double param = obj.polynomial_->at(i);
if (param != 0) {
os << param << " * x^" << i << " + ";
}
}
os << obj.polynomial_->at(0) << std::endl;
return os;
}
int main() {
Poly a = {1, 2, 3};
Poly b = {4, 5};
Poly c = a + b;
Poly d;
std::cout << a << b << c << d;
a += {1, 1};
std::cout << a;
return 0;
}
In the first case, with operator+, conceptually there's not much you can do. You'll need the temporary variable and you'll have to return it by value.
In the second case instead you implementing operator+= using operator+ and therefore making a copy which is then copied within the object itself with operator=. This is extremely inefficient.
For the above reasons, often, people prefer to implement operator+= first, and then implement operator+ as:
Poly Poly::operator+(const Poly& rhs) {
return Poly(*this) += rhs;
}
Which is the opposite of what you are doing here.

operator overloading +=

I must write operator overloading += but I don't know how to do it correctly (I began to write it a the end of code it wasn't correct so i delete all except you see).
#include <iostream>
using namespace std;
class dek
{
private:
int *x,na4,kon,n,razmer;
public:
dek(int m)
{
x=new int[m];
n=m;
na4=1;
kon=0;
razmer=0;
}
~dek()
{
delete [] x;
}
void v_n(int a)
{
if(razmer!=n)
{
na4--;
if(na4<0)na4=n-1;
x[na4]=a;
razmer++;
}
else cout<<"dek polon\n";
}
void v_k(int b)
{
if(razmer!=n)
{
kon++;
if(kon>n-1)kon=0;
x[kon]=b;
razmer++;
}
else cout<<"dek polon\n";
}
int size()
{
return razmer;
}
void u_n()
{
if(razmer!=0)
{
na4++;
if(na4>n-1)na4=0;
razmer--;
}
else cout<<"dek pust\n";
}
void u_k()
{
if(razmer!=0)
{
kon--;
if(kon<0)kon=n-1;
razmer--;
}
else cout<<"dek pust\n";
}
void pe4at()
{
int i=na4;
if(razmer!=0)
{
while(1)
{
cout << x[i] << " ";
if(i==kon)break;
i++;
if(i>n-1)i=0;
}
cout << "\n";
}
}
dek& operator = (dek const& b)
{
if(&b!=this)
{
delete [] x;
x=new int[b.n];
n=b.n;
razmer=b.razmer;
na4=b.na4;
kon=b.kon;
if(razmer!=0)
{
int i=na4;
while(1)
{
x[i]=b.x[i];
if(i==kon)break;
i++;
if(i>n-1)i=0;
}
}
}
return *this;
}
dek const operator +(dek const& b)const
{
dek s(n+b.n);
s.n=n+b.n;
s.razmer=razmer+b.razmer;
s.na4=0;
s.kon=s.razmer-1;
if(razmer!=0)
{
int j=0,i=na4;
while(1)
{
s.x[j]=x[i];
if(i==kon)break;
i++;
if(i>n-1)i=0;
j++;
if(j>s.n-1)j=0;
}
}
if(b.razmer!=0)
{
int j=razmer,i=b.na4;
while(1)
{
s.x[j]=b.x[i];
if(i==b.kon)break;
i++;
if(i>b.n-1)i=0;
j++;
if(j>s.n-1)j=0;
}
}
return s;
}
dek operator +=(dek const& b)
{
}
};
Well, the results of a += b; should be equivalent to a = a + b;;
since you have already defined an operator+, you know what these
semantics are. Once common practice is to define operator+= first,
and then implement operator+ (usually as a free function) in terms of
+=:
MyClass
operator+( MyClass const& lhs, MyClass const& rhs )
{
MyClass results( lhs );
results += rhs;
return results;
}
You then define operator+= to operate directly on the class members:
MyClass&
MyClass::operator+=( MyClass const& other )
{
n += other.n;
razmer += other.razmer;
// ...
return *this;
}
(Although there are good reasons for making it a non-member,
traditionally, operator+= is a member. Probably because operator=
is required to be a member.)
Also, traditionally, operator+= returns a reference, because this
most resembles the behavior of the operator on built-in types.
Finally, on a completely different issue: you're missing a copy
constructor (which in your case means a double deletion if you do copy),
and your operator= is broken (think of what will happen if the x =
new int[b.n]; fails and throws an std::bad_alloc). The classical
solution for this would be to implement deep copy in the copy
constructor (using more or less the same logic you use in setting the
variables in your assignment operator), and in the assignment operator,
to construct a copy, then swap the elements. This isn't strictly
necessary, but whatever you do, you must do the new (and anything else
which may fail) before changing the values in the object being assign.
(If you do this, the test for self assignment is useless; the need for a
test for assignment is usually a signal that the assignment operator is
broken.)
you need to implement void add(const dek &other) - split it out of "+" operator.
you can then implement + as
dek new_dek(*this);
new_dek.add(other);
return new_dek;
And you can implement += as
this->add(other);
return *this;
(assuming you change the return type of += to dek &)