I'm implementing a matrix class with some arithmetic. This is what I had as function for addition:
...
Matrix Matrix::operator+(const Matrix& other) const
{
Matrix out = *this;
out += scalar;
return out;
}
void Matrix::operator+=(const Matrix& other)
{
// Actually adding the numbers.
}
Just recently I found out that besides the copy constructor, I should also define a move constructor to avoid unnecessary copying of my matrix class. So I did that. And here's where it goes wrong. In the first line of my + operator, it will now move instead of copy and that causes off course a memory error.
So I revised to the following:
...
MatrixNT::MatrixNT(const MatrixNT&& other)
{
m_logger = LogWrapper::getLogger("MatrixNT");
m_rows = other.m_rows;
m_cols = other.m_cols;
m_data = other.m_data;
}
...
Matrix Matrix::operator+(const Matrix& other) const
{
Matrix out(*this);
out += scalar;
return out;
}
Is this the correct way of calling the copy constructor? It seems a bit odd, using the deference operator again. I can't find any examples on it.
Related
Assume I have a general Matrix class, for which I have already implemented the operator * which performs the usual matrix multiplication.
Such an operator has the following signature :
Matrix operator*(const Matrix & ) const;
I now wish to implement another * operator for an inherited class Matrix3 that represents 3x3 matrices.
It would have the following signature :
Matrix3 operator*(const Matrix3 &) const;
I am looking for the proper way of implementing this operator in order to re-use the code already written for the base class, and to minimize cost (i.e. copying).
This should work just fine:
// Either return base class
Matrix operator*(const Matrix3& other) const
{
return Matrix::operator*(other);
}
// Or construct from a Matrix
Matrix3 operator*(const Matrix3& other) const
{
return Matrix3(Matrix::operator*(other));
}
// Either construct the Matrix data in the Matrix3
Matrix3(const Matrix& other)
{
// Initialize Matrix specifics
// Initialize Matrix3 specifics
}
// Or pass the Matrix to it's base class so it can take care of the copy
Matrix3(const Matrix& other) : Matrix(other)
{
// Initialize Matrix3 specifics
}
I'm having some trouble implementing an assignment operator for a matrix class. It seems that the compiler doesn't want to recognize my overloaded assignment operator (I think?) and I'm not sure why. I know there are some internet articles on the various issues with implementing matrix classes in c++ (which have helped me get this far) but this time I can't seem to parallel my current predicament with any other help already out there. Anyway, I would greatly appreciate it if someone could help explain what I'm doing wrong. Thanks!
Here are my error messages:
In file included from Matrix.cpp:10:
./Matrix.h:20:25: error: no function named 'operator=' with type 'Matrix &(const Matrix &)'
was found in the specified scope
friend Matrix& Matrix::operator=(const Matrix& m);
^
Matrix.cpp:79:17: error: definition of implicitly declared copy assignment operator
Matrix& Matrix::operator=(const Matrix& m){ //m1 = m2
^
Matrix.cpp:89:13: error: expression is not assignable
&p[x][y] = m.Element(x,y);
~~~~~~~~ ^
3 errors generated.
Here is my assignment operator code in my .cpp file:
Matrix& Matrix::operator=(const Matrix& m){ //m1 = m2
if (&m == this){
return *this;
}
else if((Matrix::GetSizeX() != m.GetSizeX()) || (Matrix::GetSizeY()) != m.GetSizeY()){
throw "Assignment Error: Matrices must have the same dimensions.";
}
for (int x = 0; x < m.GetSizeX(); x++)
{
for (int y = 0; y < m.GetSizeY(); y++){
&p[x][y] = m.Element(x,y);
}
}
return *this;
here is my matrix header file:
class Matrix
{
public:
Matrix(int sizeX, int sizeY);
Matrix(const Matrix &m);
~Matrix();
int GetSizeX() const { return dx; }
int GetSizeY() const { return dy; }
long &Element(int x, int y) const ; // return reference to an element
void Print() const;
friend std::ostream &operator<<(std::ostream &out, Matrix m);
friend Matrix& Matrix::operator=(const Matrix& m);
long operator()(int i, int j);
friend Matrix operator*(const int factor, Matrix m); //factor*matrix
friend Matrix operator*(Matrix m, const int factor); //matrix*factor
friend Matrix operator*(Matrix m1, Matrix m2); //matrix*matrix
friend Matrix operator+(Matrix m1, Matrix m2);
Your assignment operator should be a member function, not a friend. Your other operators should take parameters as const Matrix &, otherwise you'll make a copy of the Matrix objects used by the operator.
You're taking the address of the element:
&p[x][y] = m.Element(x,y);
when you want to assign to it, like this:
p[x][y] = m.Element(x,y);
friend Matrix& Matrix::operator=(const Matrix& m);
This above part makes little sense since operator= must be defined as a member function within the class.
Actually I think your life would be a lot easier if you avoided the need for friends here (or at least so many of them). A self-sufficient public interface for a matrix should allow you to implement all the desired operators, whether or not they're members of the class.
Perhaps the first thing you should seek is that self-sufficient public interface so that you don't actually need something like a matrix multiplication operator to be a friend, since otherwise the likely temptation would be to make every operation involving matrices require access to the matrix internals.
I may have just done something stupid but I can't find the answer to this error message anywhere.
The problem I'm having is I keep getting the error
"returning a value from a constructor"
My code here is a copy constructor:
RealBox::RealBox(const RealBox& rhs)
{
if(this != &rhs)
{
m_boxsize = rhs.m_boxsize;
delete[] m_reals;
m_reals = new float [m_boxsize];
for(int i=0;i<m_boxsize;i++)
{
m_reals[i]=rhs.m_reals[i];
}
}
return *this;
}
From a class:
class RealBox
{
private:
float* m_reals; // Array of Real Numbers
int m_boxsize; // number of Real Numbers
public:
RealBox(int s, float a);
~RealBox();
const RealBox& operator=(const RealBox& rhs);
// Purpose: Copy Constructor
// Parameters: rhs - RealBox to be copied
// Postconditions: *this == rhs
RealBox(const RealBox& rhs);
void set( int i, float x);
friend std::ostream& operator<< (std::ostream& out,
const RealBox& box);
};
I'm sure I've just done something stupid but I can't figure it out, any help would be greatly appreciated.
Get rid of return *this; from your copy constructor.
PS - I don't think it is valid for a copy constructor to ever be passed a reference to *this and so you don't have to protect against it. If it were somehow to occur, either the passed argument to be copied from is itself not constructed, or you are re-constructing an already constructed object. Either way it's wrong.
Do not return in a copy ctor.
return *this;is error.
I think that you take the assignment operator and copy constructor function confused.
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.