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 &)
Related
While in assignment operator overloading why we return a reference to the object and why it can't return a const-reference? For example, in this case:
MyClass& MyClass::operator=(const MyClass &rhs) {
... // Do the assignment
return *this;
}
Why we can't return a constant reference like:
const MyClass& MyClass::operator=(const MyClass &rhs) {
... // Do the assignment operation!
return *this; // Return a reference to myself.
}
You can, but the users of MyClass may be surprised.
Usually, references can be taken to assignments (and less often, assignments can be assigned again). This is slightly confusing to word correctly, so here's what it looks like:
int a = 4;
int &r = a = 5;
(a = 6) = 7;
This also disallows calling member functions that modify the arguments of the function, for example:
#include <iostream>
struct C
{
int value;
const C &operator=(int v){value = v; return *this;}
};
void assign_value(C &ref)
{
ref %= 4;
}
int main(void)
{
C test;
assign_value(test = 5);
std::cout << c.value << '\n';
}
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...
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.
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.
I want to make a typedef struct called pos (from position) that stores coordinates x and y. I am trying to overload some operators for this struct, but it does not compile.
typedef struct {
int x;
int y;
inline pos operator=(pos a) {
x=a.x;
y=a.y;
return a;
}
inline pos operator+(pos a) {
return {a.x+x,a.y+y};
}
inline bool operator==(pos a) {
if (a.x==x && a.y== y)
return true;
else
return false;
}
} pos;
I also wanted to know the difference between this:
inline bool operator==(pos a) {
if(a.x==x && a.y== y)
return true;
else
return false;
}
And this:
bool operator==(pos a) const {
if(a.x==x && a.y== y)
return true;
else
return false;
}
The breakdown of your declaration and its members is somewhat littered:
Remove the typedef
The typedef is neither required, not desired for class/struct declarations in C++. Your members have no knowledge of the declaration of pos as-written, which is core to your current compilation failure.
Change this:
typedef struct {....} pos;
To this:
struct pos { ... };
Remove extraneous inlines
You're both declaring and defining your member operators within the class definition itself. The inline keyword is not needed so long as your implementations remain in their current location (the class definition)
Return references to *this where appropriate
This is related to an abundance of copy-constructions within your implementation that should not be done without a strong reason for doing so. It is related to the expression ideology of the following:
a = b = c;
This assigns c to b, and the resulting value b is then assigned to a. This is not equivalent to the following code, contrary to what you may think:
a = c;
b = c;
Therefore, your assignment operator should be implemented as such:
pos& operator =(const pos& a)
{
x = a.x;
y = a.y;
return *this;
}
Even here, this is not needed. The default copy-assignment operator will do the above for you free of charge (and code! woot!)
Note: there are times where the above should be avoided in favor of the copy/swap idiom. Though not needed for this specific case, it may look like this:
pos& operator=(pos a) // by-value param invokes class copy-ctor
{
this->swap(a);
return *this;
}
Then a swap method is implemented:
void pos::swap(pos& obj)
{
// TODO: swap object guts with obj
}
You do this to utilize the class copy-ctor to make a copy, then utilize exception-safe swapping to perform the exchange. The result is the incoming copy departs (and destroys) your object's old guts, while your object assumes ownership of there's. Read more the copy/swap idiom here, along with the pros and cons therein.
Pass objects by const reference when appropriate
All of your input parameters to all of your members are currently making copies of whatever is being passed at invoke. While it may be trivial for code like this, it can be very expensive for larger object types. An exampleis given here:
Change this:
bool operator==(pos a) const{
if(a.x==x && a.y== y)return true;
else return false;
}
To this: (also simplified)
bool operator==(const pos& a) const
{
return (x == a.x && y == a.y);
}
No copies of anything are made, resulting in more efficient code.
Finally, in answering your question, what is the difference between a member function or operator declared as const and one that is not?
A const member declares that invoking that member will not modifying the underlying object (mutable declarations not withstanding). Only const member functions can be invoked against const objects, or const references and pointers. For example, your operator +() does not modify your local object and thus should be declared as const. Your operator =() clearly modifies the local object, and therefore the operator should not be const.
Summary
struct pos
{
int x;
int y;
// default + parameterized constructor
pos(int x=0, int y=0)
: x(x), y(y)
{
}
// assignment operator modifies object, therefore non-const
pos& operator=(const pos& a)
{
x=a.x;
y=a.y;
return *this;
}
// addop. doesn't modify object. therefore const.
pos operator+(const pos& a) const
{
return pos(a.x+x, a.y+y);
}
// equality comparison. doesn't modify object. therefore const.
bool operator==(const pos& a) const
{
return (x == a.x && y == a.y);
}
};
EDIT OP wanted to see how an assignment operator chain works. The following demonstrates how this:
a = b = c;
Is equivalent to this:
b = c;
a = b;
And that this does not always equate to this:
a = c;
b = c;
Sample code:
#include <iostream>
#include <string>
using namespace std;
struct obj
{
std::string name;
int value;
obj(const std::string& name, int value)
: name(name), value(value)
{
}
obj& operator =(const obj& o)
{
cout << name << " = " << o.name << endl;
value = (o.value+1); // note: our value is one more than the rhs.
return *this;
}
};
int main(int argc, char *argv[])
{
obj a("a", 1), b("b", 2), c("c", 3);
a = b = c;
cout << "a.value = " << a.value << endl;
cout << "b.value = " << b.value << endl;
cout << "c.value = " << c.value << endl;
a = c;
b = c;
cout << "a.value = " << a.value << endl;
cout << "b.value = " << b.value << endl;
cout << "c.value = " << c.value << endl;
return 0;
}
Output
b = c
a = b
a.value = 5
b.value = 4
c.value = 3
a = c
b = c
a.value = 4
b.value = 4
c.value = 3
Instead of typedef struct { ... } pos; you should be doing struct pos { ... };. The issue here is that you are using the pos type name before it is defined. By moving the name to the top of the struct definition, you are able to use that name within the struct definition itself.
Further, the typedef struct { ... } name; pattern is a C-ism, and doesn't have much place in C++.
To answer your question about inline, there is no difference in this case. When a method is defined within the struct/class definition, it is implicitly declared inline. When you explicitly specify inline, the compiler effectively ignores it because the method is already declared inline.
(inline methods will not trigger a linker error if the same method is defined in multiple object files; the linker will simply ignore all but one of them, assuming that they are all the same implementation. This is the only guaranteed change in behavior with inline methods. Nowadays, they do not affect the compiler's decision regarding whether or not to inline functions; they simply facilitate making the function implementation available in all translation units, which gives the compiler the option to inline the function, if it decides it would be beneficial to do so.)
try this:
struct Pos{
int x;
int y;
inline Pos& operator=(const Pos& other){
x=other.x;
y=other.y;
return *this;
}
inline Pos operator+(const Pos& other) const {
Pos res {x+other.x,y+other.y};
return res;
}
const inline bool operator==(const Pos& other) const {
return (x==other.x and y == other.y);
}
};
bool operator==(pos a) const{ - this method doesn't change object's elements.
bool operator==(pos a) { - it may change object's elements.