Change value pointed by this pointer - c++

I wrote this working piece of code for my matrix struct. It computes the value of a square matrix raised to the e-th power, but this is irrelevant. I want to know what is happening in the last lines.
Is the value of p being copied to the location pointed by this? Is it a shallow copy or a deep copy?
Is this being changed? I don't think so because it's const.
How can I implement that copy to make it run faster?
matrix& operator ^=(int e)
{
matrix& b = *this;
matrix p = identity(order());
while (e) {
if (e & 1)
p *= b;
e >>= 1;
b *= b;
}
*this = p;
return *this;
}

One of the following will make it faster, if you're added appropriate buffer-stealing support to your class:
Replace
*this = p;
by either (preferred in C++11)
*this = std::move(p);
or (for C++03, should still work ok in C++11)
swap(p); // if swap is a member
swap(*this, p); // if it's not
However, since you can't overwrite the left hand side in place, best is to implement operator^, and write operator^= in terms of that:
matrix operator^(const matrix& b, int e)
{
matrix p = identity(b.order()); // move or elision activated automatically
while (e) {
if (e & 1)
p *= b;
e >>= 1;
b *= b;
}
return p; // move or NRVO activated automatically
}
matrix& operator^=(int e)
{
*this = (*this) ^ e; // move activated automatically since RHS is temporary
// ((*this) ^ e).swap(*this); in C++03
return *this;
}
Just noticed you are overwriting *this in place, with successive squares.

*this = p; invokes your matrix's operator=(matrix) method, if it has one, otherwise it invokes a compiler-generated operator=() that simple performs a member-by-member copy of p's fields into this's fields (using their respective operator=() implementations).

Related

Overloading the assignment operator or use the default one?

If I have
Class A {
int x;
};
Class B {
vector<A> y;
//...
};
And I want to overload the assignment operator = in B. Will using the default = operator be enough? Will it just use the = operator of vector on y member?
EDIT: say I wanted to implement something like that myself, so that b = k will work if both b and k are of type B. would I need to explicitly call the vector destructor to free the y member of b, inside the implementation?
How will it look like?
B& B::operator=(const B& b) {
if (this == &b) {
return *this;
}
y = b.y;
return *this;
}
Will the original vector this->y destructed here? why?
Will using the default = operator be enough?
Yes, it's sufficient, unless you have any resources that need special treatment or parameters.
Will it just use the = operator of vector on y member?
Yes, the generated default assignment operator/copy constructor will call any assignment operators/copy constructors available for member variables automatically.
B& B::operator=(const B& b) {
if (this == &b) {
return *this;
}
y = b.y;
return *this;
}
Will the original vector this->y destructed here? why?
Yes, it will be "destructed", since the operator=() definition of vector<A> implies to do so.
It's not really the destructor function is called, but the implementation of the assignment operator does imply the same behaviour as there would be a new instance constructed, and all of the contained member destructors will be called when the vector is cleared.
If you don't have special cases (like owning pointers, or unique_ptr), you can just not-define it and use the default one. In your case it should be fine.
In case of owning pointers, you would suddenly have two objects pointing to the same data in memory, which might not be the behaviour you want (same goes for shared_ptr.
unique_ptr can't be copied, so the default assignment operator won't work in this case and you'd have to write an overload.

Assignment Operator Overload in c++

I realize that there are examples after examples of overloading the assignment operator on the web, but I have spent the last few hours trying to implement them in my program and figure out how they work and I just can't seem to do it and any help would be greatly appreciated.
I am trying to implement an overloaded assignment operator function.
I have 3 files working, the Complex.h header file, a Complex.cpp definition file, and a .cpp file I'm using as a driver to test my Complex class.
In the Complex.h header file my prototype for the assignment operator:
Complex &operator= (Complex&);
And so far what I have for the definition of the overloaded operator in my .cpp file is:
Complex &Complex::operator=(Complex& first)
{
if (real == first.real && imaginary == first.imaginary)
return Complex(real, imaginary);
return first;
};
And the way I'm calling my assignment operator in my functions is:
x = y - z;
So specifically, my problem is that when I call the overloaded assignment operator with x = y -z, it doesn't assign the passed in value to x when I return the passed in value and I'm unable to figure out why from numerous examples and explanations on the web, any help would be greatly appreciated and I thank you for any help ahead of time.
I think you need the following operator definition
Complex & Complex::operator =( const Complex &first )
{
real = first.real;
imaginary = first.imaginary;
return *this;
};
You have to return reference to the object that is assigned to. Also the parameter should be a constant reference. In this case you may bind the reference to a temporary object or you have to write also a move assignment operator.
In your implementation of the copy assignment operator you do not change the assigned object.:) You simply create a temporary and return reference to this temporary or return reference to first.
Assignment takes in two objects, the object to be assigned to, and the object with the desired value.
Assignment should:
modify an existing object, the object being assigned to
Assignment should not:
create a new object
modify the object that has the desired value.
So let's say the object type we're dealing with is:
struct S {
int i;
float f;
};
A function that performs assignment might have the signature:
void assignment(S &left_hand_side, S const &right_hand_side);
And it would be used:
S a = {10, 32.0f};
S b;
assignment(b, a);
Notice:
the left hand side object is modifiable, and assignment will modify it, rather than create a new object.
the right hand side object, the object with the desired value, is not modifiable.
Additionally, in C++ the built-in assignment operation is an expression rather than a statement; it has a value and can be used as a subexpression:
int j, k = 10;
printf("%d", (j = k));
This sets j equal to k, and then takes the result of that assignment and prints it out. The important thing to note is that the result of the assignment expression is the object that was assigned to. No new object is created. In the above code, the value of j is printed (which is 10, because j was just assigned the value 10 from k).
Updating our earlier assignment function to follow this convention results in a signature like:
S &assignment(S &left_hand_side, S const &right_hand_side);
An implementation looks like:
S &assignment(S &left_hand_side, S const &right_hand_side) {
// for each member of S, assign the value of that member in
// right_hand_side to that member in left_hand_side.
left_hand_side.i = right_hand_side.i;
left_hand_side.f = right_hand_side.f;
// assignment returns the object that has been modified
return left_hand_side;
}
Note that this assignment function is not recursive; it does not use itself in the assignment, but it does use assignment of the member types.
The final piece of the puzzle is getting the syntax a = b to work, instead of assignment(a, b). In order to do this, all you have to do is make assignment () a member function:
struct S {
int i;
float f;
S &assignment(S &left_hand_side, S const &right_hand_side) {
left_hand_side.i = right_hand_side.i;
left_hand_side.f = right_hand_side.f;
return left_hand_side
}
};
Replace the left_hand_side argument with *this:
struct S {
int i;
float f;
S &assignment(S const &right_hand_side) {
this->i = right_hand_side.i;
this->f = right_hand_side.f;
return *this;
}
};
And rename the function to operator=:
struct S {
int i;
float f;
S &operator=(S const &right_hand_side) {
this->i = right_hand_side.i;
this->f = right_hand_side.f;
return *this;
}
};
int main() {
S a, b = {10, 32.f};
S &tmp = (a = b);
assert(a.i == 10);
assert(a.f == 32.f);
assert(&tmp == &a);
}
Another important thing to know is that the = sign is used in one place that is not assignment:
S a;
S b = a; // this is not assignment.
This is 'copy initialization'. It does not use operator=. It is not assignment. Try not to confuse the two.
Points to remember:
assignment modifies the object being assigned to
assignment does not modify the object being assigned from.
assignment does not create a new object.
assignment is not recursive, except insofar as assignment of a compound object makes use of assignment on all the little member objects it contains.
assignment returns the object after modifying its value
copy initialization looks sort of like assignment, but has little to do with assignment.
An overloaded assignment operator should look like this:
Complex &Complex::operator=(const Complex& rhs)
{
real = rhs.real;
imaginary = rhs.imaginary;
return *this;
};
You should also note, that if you overload the assignment operator you should overload the copy constructor for Complex in the same manner:
Complex::Complex(const Complex& rhs)
{
real = rhs.real;
imaginary = rhs.imaginary;
};

Overloaded operator C++: Object = Object * Object

I'm having trouble multiplying objects using the overloaded * operator
In the class I have the operator defined as:
const Matrix operator*(Matrix& B);
The implementation is
const Matrix Matrix::operator* (Matrix& B){
Matrix r = Matrix(B.M,B.N);
for(int i = 0; i < r.M; i++){
for(int j = 0; j < r.N; j++){
r.data[i*N+j] = (*this)(i,j) * (int)B(i,j);
}
}
return r;
}
When I call
Matrix C = A * B
I will get the expected result, however calling
C = C * C
Results in an error.
I'm guessing it's to with the calling object C but I'm not sure what to do!
EDIT:
My assignment operator. Matrix R is a deep copy.
Matrix Matrix::operator=(Matrix& B){
Matrix r(M,N);
for(int i = 0; i < M; i++){
for(int j = 0; j < N; j++){
r.data[i*N+j] = B(i,j);
}
}
return r;
}
The error is because you are storing your data in a variable called "data" (which is an int[] on the heap) and you haven't overridden your assignment operator to copy the values from the object being copied into the current member variable "data". So, the default assignment operator will copy the "data" pointer for you, which in your case is from a temporary value that will be out of scope after the assignment. Your destructor will most likely delete the "data" variable you are now pointing to because the temporary goes out of scope.
You have defined your own copy constructor to establish the "data" variable on the heap. The first example you have where Matrix C = A * B will use that copy constructor, which works.
The second example uses the default assignment operator, which will only copy the data pointer from the temporary value returned from the operation. Thus, you basically have no value that data is pointing to.
You have to define an assignment operator to make this work.
Here are suggested functions to go along with your copy constructor:
void Matrix::swap(Matrix& other)
{
std::swap(M, other.M);
std::swap(N, other.N);
std::swap(data, other.data);
}
Matrix& Matrix::operator= (Matrix matrix)
{
swap(matrix);
return *this;
}
Matrix Matrix::operator* (const Matrix& B)
{
Matrix r = Matrix(B.M,B.N);
for(int i = 0; i < r.M; i++){
for(int j = 0; j < r.N; j++){
r.data[i*N+j] = (*this)(i,j) * (int)B(i,j);
}
}
return r;
}
This works well because the copy constructor will be used for "matrix" in assignment operator (operator=). Then, the swap function will trade the "data" array with the temporary copy of Matrix. Therefore, you will copy the appropriate "data" from the operation*'s temporary variable.
This has nothing to do with "calling object C".
The first version
Matrix C = A * B;
uses constructor(s) or class Matrix to initialize new object C.
The second version
C = C * C;
uses assignment operator of class Matrix to assign new value to an existing object C.
You managed to screw up the assignment operator declaration/implementation somehow (which you don't show in the code you posted), which is why the second version does not compile.
There are problems with your operator * declaration as well. Even if you want to have it as class member, a more meaningful way to declare it would be
Matrix Matrix::operator* (const Matrix& B) const {
...
Note how const qualifiers are placed.
EDIT: So, here's your problem. Your assignment operator is completely broken.
Firstly, you declared your assignment operator as
Matrix Matrix::operator=(Matrix& B)
This operator cannot accept temporary objects on the right-hand side because you failed to declare the parameter as const. Non-const references cannot be bound to temporary objects. And in C = C * C the right-hand side of assignment is actually a temporary object produced by *operator.
Redeclare your assignment operator as
Matrix &Matrix::operator=(const Matrix& B)
Note, it accepts a const reference and returns a reference.
Secondly, your assignment operator is supposed to assign to *this, not to some standalone temporary object. And it is supposed to return a reference to *this. In other words, the implementation should be something along the lines of
Matrix &Matrix::operator=(const Matrix& B){
// Resize `*this` to match the size of `B`
for(int i = 0; i < M; i++){
for(int j = 0; j < N; j++){
this->data[i*N+j] = B(i,j);
}
}
return r;
}
Try to define the operator like this:
Matrix operator* (const Matrix& x, const Matrix& y)
{
//...
}

Assignment operator and copy constructor after matricies multiplication

Have problem with copy constructor and assignment operator. Have written code to multiply matricies:
Matrix& Matrix::operator * (const Matrix &second) const
{
// Create result matrix
Matrix result(Rows(), second.Columns());
// Multiply matricies
for (unsigned i = 0; i < Rows(); i++)
{
for (unsigned j = 0; j < second.Columns(); j++)
{
result[i][j] = 0.0;
for (unsigned k = 0; k < Columns(); k++)
{
result[i][j] += m_matrix[i][k] * second[k][j];
}
}
}
return result;
}
In Main code I call the operator:
Matrix C = A * B;
However code destroys result variable before assignment, how to write such code correctly to return result matrix? Copy constructor is:
Matrix::Matrix(const Matrix& matrix)
{
AllocateMatrixArray(matrix.Rows(), matrix.Columns());
CopyMatrixData(matrix);
}
Assignment operator is:
Matrix& Matrix::operator = (const Matrix& other)
{
AllocateMatrixArray(other.Rows(), other.Columns());
CopyMatrixData(other);
return *this;
}
However I see that compiler does not use it - copy constructor is enough.
Your code returns a reference to a local variable, which will be destroyed at the end of the function's scope. Don't do that:
Matrix Matrix::operator * (const Matrix &second) const {
// same as above
}
Note that the return value is now a Matrix instead of a Matrix&.
You should not be returning a reference to local variable. By convention the opertor*(I mean the two argument version of course) returns a copy to the result. Same holds true for the other operations like operator+, operator- and so on. A reference is returned by the moifying versions of those operators like operator *=, operator += and so on.
If you want to write expressions like C = A*B all C A and B must be "values".
So the return value of operator* must be matrix and not matrix&, espscialy if the & refers to a local variable (like result) thet will be destroyed at } (hence before = is executed).
That said, there are some more issues:
The sample Matrix C = A*B is not an assignment: an assignment happens the the value of an already existent object is changed. But Matrix C is created contextually: in fact, what it is called here, is the Matrix constructor (copy constructor, in this case)
There could be memory leaks: Although I don't see how the matrices data are handled, your operator=
seems to allocate new space and then copy the data in it. But what happens to the space containing the old data? Does it remain forgotten around? Is is automatically released by a smart pointer?
Similarly, just like = should dismiss the old data, also the class itself should dismiss its own data on destruction, hence a destructor should also be implemented. Otherwise every time a Matrix is dismissed (like the local result), its data will stay around.

C++ operator destroys input variables

This is probably just me being stupid somehow or the other, but I am relatively new to C++, so forgive me the idiocy. I'm trying to teach myself how to use operators. I've defined a very basic operator as follows:
Matrix::Matrix operator+(Matrix a1, Matrix a2) {
if(a1.rows != a2.rows || a1.cols != a2.cols) {
std::cout << "ERROR: Attempting to add matrices of non-equal size." << std::endl;
exit(6);
}
int i, j;
Matrix c(a1.rows, a1.cols);
for(i = 0; i < a1.rows; i++)
for(j = 0; j < a1.cols; j++)
c.val[i][j] = a1.val[i][j] + a2.val[i][j];
return c;
}
The class Matrix represents a matrix, and has a constructor that takes two ints as input (the number of rows and columns in the matrix, respectively), and creates a 2D array of doubles of the appropriate size (named val). This function works as supposed to in that the value for c is correct, but it also appears to destruct a1 and a2. That is, if I write
Matrix c = a + b;
It gives the right result, but a and b are no longer usable, and I get a glibc error at the end of the code claiming I am trying to destruct a and b when they have already been destructed. Why is this?
Your signature is wrong:
Matrix operator+(Matrix a1, Matrix a2)
it should be
Matrix operator+(const Matrix& a1, const Matrix& a2)
The reason it appears to destroy a1 and a2 is because, well, it is, since those are temporary copies created in the method scope.
If the original values are destroyed, you're probably violating the rule of three. When a1 and a2 are destroyed, the destructor gets called, and you're probably deleting pointers in the destructor. But since the default copy constructor does only a shallow copy, the copied a2 and a1 will delete the original memory.
Edit: Since there are split opinions about this, I'll extend my answer:
Assume:
struct A
{
int* x;
A() { x = new int; *x = 1; }
~A() { delete x; }
};
//option 1:
A operator + (A a1, A a2)
{
A a; return a; //whatever, we don't care about the return value
}
//option 2:
A operator + (const A& a1, const A& a2)
{
A a; return a; //again, we don't really care about the return value
}
In this first example, the copy constructor is not implemented.
A copy constructor is generated by the compiler. This copy constructor copies x into the new instance. So if you have:
A a;
A b = a;
assert( a.x == b.x );
Important note that the pointers are the same.
Calling option 1 will create copies inside operator +, because the values are passed by value:
A a;
A b;
a + b;
//will call:
A operator + (A a1, A a2)
// a1.x == a.x
// a2.x == n.x
When operator + exits, it will call delete x on objects a1 and a2, which will delete the memory that is also pointed to by a.x and b.x. That is why you get the memory corruption.
Calling option 2 however, since no new objects are created because you pass by reference, the memory will not be deleted upon function return.
However, this isn't the cleanest way to solve the issue. It solves this issue, but the underlying one is much more important, as Konrad Pointed out, and I have in my original answer (although haven't given it enough importance, I admit).
Now, the correct way of solving this is properly following the rule of three. That is, have an implementation for destructor, copy constructor and assignment operator:
struct A
{
int* x;
A() { x = new int; *x = 1; }
A(const A& other) //copy constructor
{
x = new int; // this.x now points to a different memory location than other.x
*x = other.(*x); //copy the value though
}
A& operator = (const A& other) //assignment operator
{
delete x; //clear the previous memory
x = new int;
*x = other.(*x); //same as before
}
~A() { delete x; }
};
With this new code, let's re-run the problematic option 1 from before:
A a;
A b;
a + b;
//will call:
A operator + (A a1, A a2)
// a1.x != a.x
// a2.x != n.x
Because the copies a1 and a2 now point to different memory locations, when they are destroyed, the original memory is intact and the original objects - a and b remain valid.
Phew! Hope this clears things up.
I’m assuming that you are allocating dynamic memory inside the Matrix class using new and didn’t implement a custom copy constructor, thus violating the rule of three.
The cause of the error would then be that the local copy of the Matrix instances reuses the dynamic memory of the argument instances, and their destructors free it at the end of the method.
The solution is very simple: Don’t use pointers. Instead, you could use a nested std::vector to store the data.
Furthermore, the head of the operator is mangled. Depending on where you declare the function, it must either look like this, if you define the operator inside the class:
ReturnType operator +(Arg1)
Or, if you define it outside the class, it needs to look like this:
ReturnType operator +(Arg1, Arg2)
Yours is a wild mix of both. I’m assuming that your operator definition should look as follows:
Matrix operator +(Matrix a, Matrix b) { … }
If your code compiles then this is either an error in the compiler or you are using a very weird class structure indeed. Furthermore, as Luchian pointed out, it’s more efficient to pass the arguments as const& rather than by value. However, you should first make your code run correctly.
As Luchian Grigore pointed out, your signature is wrong and should be:
Matrix operator+(const Matrix& a1, const Matrix& a2)
But even this signature should not itself spoil a and b. But because you are copying arguments, I have another suspicion.
Have you defined your own copy constructor? I think you may be deleting the old variables when you are copying their values to the operator's arguments.
Please share your copy constructor (and preferably also operator= and the two-argument constructor that you use in this operator)
Since the size of the matrix is given at runtime, I suppose that the Matrix class hold a pointer that is initialized with a dynamically allocated array that is deleted by the destructor.
In that case, the copy constructor and the assignment operator must also be definedin order to allocate the copies of what the a matrix holds.
Not doing that, the default copy and assignment will just reassign the pointers, letting you with two or more Matrix holding a same array. And when one is destroyed (thus deleting the array) the others remain dangling.