I was reading a book on operator overloading in c++ and I encountered the following code:
class Array {
...
public:
Array & operator << ( int x) {
// insert x at the end of the array
}
};
Next It says: that overloading of the form a << x << y << z ;
wll not workSo It suggests that second invocation is treated as :( (a << x)<< y ) << z .so it recommends using return *this;
But I am not getting how return *this functions here? Please help!Here is the entire code:
#include <iostream>
#include <cstdlib>
using namespace std;
class Array {
int *a;
int capacity;
int size;
int incr;
public:
Array (int c=10) {
a = new int[c];
capacity = c;
for (int i=0; i<c; i++) a[i]=0;
size=0;
incr = c;
}
Array &operator << (int x) {
if(size<capacity) a[size++] = x;
else {
int *tmp = new int [capacity+incr];
for (int i=0; i<size; i++) tmp[i]=a[i];
delete[] a;
a = tmp;
a[size++]=x;
capacity = capacity+incr;
}
return *this;
};
int operator [] (int i) {
if(i<size) return a[i];
};
};
int main (int argc, char *argv[]) {
int s = atoi (argv[1]);
Array A (s);
for (int i=0; i<s; i++) A << i << i+1;
for (int i=0; i<s; i++) cout << A[i] << endl;
}
This really has nothing to do with operator overloading. It's called chaining and it's easier to explain using regular member functions. Suppose you defined a member function called insert like this:
Array& insert(int x) {
// insert x at the end of the array
return *this;
}
The return *this will return a reference to the current object so that you can chain calls like this:
Array a;
a.insert(0).insert(1).insert(2);
Which is essentially equivalent to:
Array a;
a.insert(0);
a.insert(1);
a.insert(2);
Each call to insert() will return a reference to the original object, allowing other calls to be made using that returned reference. You can overload the << operator to do the same thing:
Array& operator<<(int x) {
// insert x at the end of the array
return *this;
}
Now you can chain calls like this:
Array a;
a << 0 << 1 << 2;
You may be getting confused because of the spacing of Array &operator <<. The return value of the function is Array&, a reference to the array object.
Here's an example. In your call A << i << i+1, the A << i is called first and a reference to the updated A is returned. Next A << i+1 is called, with that new reference.
Yes everything is ok with your code. operator << in your semantics will and returning refference to same object which called it. You can see same in code of operator << of std::ostream and operator >> of std::istream.
Related
I am trying to insert int array x to int *v. here is my code . please provide me with optimal solutions and the reason behind it.
there is an error in this line. Instead of copying array value its taking garbage value. line v1=x;
class vector
{
int *v;
int size;
public:
vector(int m)
{
v = new int[size = m];
for (int i = 0; i < size; i++)
v[i] = 0;
}
vector(int *a)
{
for (int i = 0; i < size; i++)
v[i] = a[i];
}
int operator *(vector &y)
{
int sum = 0;
for (int i = 0; i < size; i++)
sum += v[i] * y.v[i];
return sum;
}
void disp()
{
for (int i = 0; i < size; i++)
cout << v[i] << " ";
cout << "\n";
}
};
int main()
{
clrscr();
int x[3] = { 1,2,3 };
int y[3] = { 4,5,6 };
vector v1(3);
//v1.disp();
vector v2(3);
v2.disp();
v1 = x;
v1.disp();
//v2=y;
v2.disp();
int r = v1 * v2;
cout << "R = " << r;
getch();
return 0;
}
You forgot to add the assignment operator in your vector class:
vector & operator=(int *a)
{
for (int i = 0; i < size; i++)
v[i] = a[i];
return *this;
}
In the the line
v1=x;
May be, you are expecting it to invoke the second constructor which takes int* as argument. But it won't happen.
It can be seen as Type Conversion from Basic type to Class type. where we expect appropriate constructor will get invoked.
see http://www.hexainclude.com/basic-to-class-type-conversion/
But remember, Constructor will be invoked only once after the creation of object.
Here, in the line
vector v1(3);
the first constructor was already invoked. Then the line
v1=x;
won't invoke the second constructor now.
For every class, = operator is default overloaded . That is the reason why we can easily assign objects to one another.
Therefore, the line v1=x invokes default overloaded assignment = operator.
Here, it treats address of array x i.e., &x[0] as address of class object. As it is not address of vector class object
=> it results a Segmentation fault.
YOUR ANSWER
To assign int array to int pointer i.e., to the member variable int* v of the vector class,
overload assignment operator = inside the class .
or
Initialize the class object to array in first line itself. i.e.,
vector v1=x; // modify the class constructor to have size as a constant.
I am a c++ beginner and i have trouble compiling the following code
the problem is in the statement T a = s where s is a char* containing abcde.
The goal here is to declare an object of T and initializing it with s.
I also have trouble in this line for(int i = 0; i < a(); i++).
I don't know how can i use a constructor or a function named a() to return the size.
This my code :
#include <iostream>
#include <cassert>
using namespace std;
class T{
int nb ;
char *pc;
public:
T(int);
~T();
T(T&);
char& operator[](int);
T(const char* s){
int n ;
for(int i = 0 ; s[i] != '\0' ;i++ ) n++ ;
nb = n ;
pc= new char[nb];
for(int i=0 ; i < nb ; i++) pc[i] = s[i];
}
};
T::T(int k){
assert(k > 0);
nb = k;
pc = new char[nb];
}
T ::~T(){
if( pc != NULL) delete [] pc;
}
T::T(T& t){
nb=t.nb;
delete[] pc;
pc = new char[nb];
for(int i=0 ; i < nb ; i++) pc[i] = t.pc[i];
}
char& T::operator[](int index){
assert(index >=0 && index <= nb);
return pc[index];
}
int main(){
char* s = "abcde";
T a = s;
for(int i = 0; i < a(); i++)
cout << a[i] << " ";
cout << endl;
T b = a;
b[1] = '*';
b[3] = '*';
for(int i = 0; i < b(); i++)
cout << b[i] << " ";
cout << endl;
return 0;
}
i get the following error :
invalid initialization of non-const reference of type 'T&' from an rvalue of type 'T'|
You are misunderstanding the "assignment" when defining the object.
When defining an object like you do with
T a = s;
it's not an assignment, it's an object construction and you need a constructor taking a const char* argument.
If on the other hand you do
T a;
a = s;
then it's an assignment. Of course, this relies on T having a default constructor (a constructor that doesn't take any arguments).
The error you get now is because you need a copy-constructor that takes its argument by constant reference. The definition
T a = s;
is actually equal to
T a = T(s);
And the T(s) creates a temporary object that will be destructed once the full initialization of a is complete. And non-constant references can not be bound to temporary object, so your copy-constructor needs to accept a const T& argument.
Initialization doesn't use operator=. It uses constructor instead, despite the = sign in syntax. So you need to have constructor with signature T::T(char*). By the way, I strongly recommend making it a const char* to avoid compiler yelling at you for assigning to it string literals.
I am trying to do a simple thing but suddenly stuck in between .
Here in my code I am trying to call a constructor in which i would only pass the length, my first constructor initializes an array of size = length with all elements 0.
Then i am passing the array to the constructor to give the previously defined array its values
here is the sample :
class myvector
{
int *arr;
int length;
public :
myvector(int);
myvector(int *);
};
myvector :: myvector (int len)
{
arr = new int [length = len];
for ( int i=0;i< length;i++)
{
arr[i] = 0;
}
}
myvector :: myvector ( int *ex)
{
for ( int i=0;i< length;i++)
{
cout << ex[i] << " " << length <<" ";
arr[i] = ex[i];
cout << arr[i]<< " ";
}
}
int main()
{
myvector v1(5);
int x[5] = {2,3,4,45,6};
v1 = x;
}
Here in my second constructor length which was defined in first constrcutor lost its values , also array arr loses its values
Did I do something ?
Please elaborate me on this
I don't think you quite get what the circumstances are in which constructors are invoked. The line v1 = x doesn't put the values into the memory allocated during the first constructor call. Rather, it constructs a new myvector (using the second constructor) and copies it into v1. The stuff you do during the first constructor call is lost.
It sounds like you want to define an assignment operator, not a constructor taking an int* argument. Also, in general you should declare single-argument constructors as explicit to prevent this sort of thing from happening accidentally.
First of all, when specifying a size of array like this, you should provide a constant value. See here. And I really encourage you to use std::vector<> for such tasks.
But anyway, like Sneftel mentioned, seems like you want to define an assignment operator (see here for more information about overloading operators in tasks like yours).
Here how I'd implemented it(NOT and ideal solution, but it works, and gives a basic idea):
#include <iostream>
using namespace std;
class myvector
{
int *arr;
int length;
public :
//I completely removed second constructor
myvector(int);
~myvector();
void operator=(const int* otherArray);
void printArray();
};
myvector::myvector (int len)
{
length = len;
arr = new int[length]; // This is the way, how you can handle a non constant array sizes
for ( int i=0;i< length;i++)
{
arr[i] = 0;
}
}
void myvector::printArray()
{
for(unsigned i = 0; i < length; ++i)
cout<<"arr["<<i<<"] = "<<arr[i]<<endl;
}
//Here's an overloaded '=' operator.
//int x[5] = {2,3,4,45,6};
//myvector v;
//v = x; - here this function is called
void myvector::operator=(const int* otherArray)
{
for(unsigned i = 0; i < length; ++i)
arr[i] = otherArray[i];
}
myvector::~myvector()
{
delete []arr; // You should ALWAYS delete what you allocated with new
}
int main()
{
myvector v1(5);
int x[5] = {2,3,4,45,6};
v1 = x;
v1.printArray();
}
Yesterday my class had a laboratory exam where-in we had to make a matrix class and overload the operation+(). I thought that I had it correct until I went to go do my unit testing... I know this is a lot of text; however, I spent the remainder of the lab trying to figure out what was going wrong and could NOT figure out why the Temporary Object Matrix was going out of scope prior to the assignment operator call.
Code as follows:
Matrix Header
#include <iostream>
#include <iomanip>
using namespace std;
class Matrix
{
Public:
// Constructor and Destructor Suite
Matrix(int x, int y); // Lab TA stated that Matricies would never go above two dimensions
~Matrix();
// Access and Mutation
void set(int row, int column, int value); // This function sets the value of a given matrix coordinate at row, column to value
int get(int row, int column) const; // This function returns the value of a matrix at row, column
Matrix& operator=(const Matrix& Q)
{
cout << "Called Assignment" << endl;
int r, c;
r = Q.rows; c = Q.columns;
for (int i = 0; i < r; i++)
{
for (int k = 0; k < c; k++)
{
cout << "Address of Calling Objet pointer Int: " << this->pMatrixOfInt[i][k] << setw(5) << *this->pMatrixOfInt[i][k] << endl;
cout << "Address of Reference Object: " << Q.pMatrixOfInt[i][k] << setw(5) << *Q.pMatrixOfInt[i][k] << endl;
*(this->pMatrixOfInt[i][k]) = *(Q.pMatrixOfInt[i][k]);
}
}
return *this;
}
const Matrix operator+(const Matrix& Q);
friend ostream& operator<<(ostream& output, const Matrix& Q);
friend istream& operator>>(istream& input, Matrix& Q);
private:
int rows, columns;
int* pMatrixOfInt[50][50]; // Specification document said that these values would never go above 50
};
Matrix.cpp
/*
Matrix Class Definition
14 March 2014
*/
#include <iomanip>
#include <iostream>
#include "Matrix.h"
// Constructor
Matrix::Matrix(int x, int y)
{
cout << "Constructor Called" << endl;
this->rows=x;
this->columns=y;
for (int i=rows-1; i>=0; i--) // If X and Y are both 50 then the starting value
{ // for i and k should be 49 because of how arrays
for (int k=columns-1; k>=0; k--) // are indexed. Hence the rows-1
{
pMatrixOfInt[i][k] = new int;
}
}
}
// Destructor
Matrix::~Matrix()
{
cout << "Destructor Called" << endl;
for (int i=rows-1; i>=0; i--) // If X and Y are both 50 then the starting value
{ // for i and k should be 49 because of how arrays
for (int k=columns-1; k>=0; k--) // are indexed. Hence the rows-1
{
delete pMatrixOfInt[i][k];
}
}
}
// Access and Mutation
void Matrix::set(int row, int column, int value)
{
*pMatrixOfInt[row][column] = value;
}
int Matrix::get(int row, int column) const
{
return *pMatrixOfInt[row][column];
}
// Overloaded Addition Operator (Possible Scope Problem)
const Matrix Matrix::operator+(const Matrix& Q)
{
cout << "Addition Operator Called" << endl;
int rows, columns;
rows = Q.rows;
columns = Q.columns;
Matrix newMatrix(rows, columns);
cout << "newMatrix Rows: " << newMatrix.rows << " -- newMatrix columns: " << newMatrix.columns << endl; // Make a new matrix. Constructor will initialize the pointer Matrix
int newValue;
for (int i=0; i<rows; i++)
{
for (int k=0; k<columns; k++)
{
newValue = this->get(i,k);
newValue += Q.get(i,k);
newMatrix.set(i,k, newValue);
cout << setw(5) << newMatrix.get(i, k);
}
cout << "\n";
}
return newMatrix;
}
// Friend definitions for i/ostreams.
ostream&::operator<<(ostream& output, const Matrix& Q)
{
for (int r = 0; r<Q.rows; r++)
{
for (int c = 0; c<Q.columns; c++) // hahaha
{
output << setw(4) << Q.get(r,c);
}
output << "\n";
}
return output;
}
istream&::operator>>(istream& input, Matrix& Q)
{
int value;
for (int r = 0; r<Q.rows; r++)
{
for (int c = 0; c<Q.columns; c++)
{
input >> value;
Q.set(r,c,value);
}
}
return input;
}
When I tried to do something like this:
newMatrix = oldMatrixA + oldMatrixB;
cout << newMatrix;
I received the following series of outputs and then a BLOCK_HEADER_ERROR:
Addition Operator Called
0 1 2 3
1 3 5 7
Destructor Called
Assignment Called
Lots of output here regarding address of calling object and value along with the reference object and value of that too
!!!BLOCK_HEADER_ERROR!!!
Can anyone tell me why the Temporary Object returned by the addition operator is going out of scope prior to the assignment operator even though they are on the same line and newMatrix is a return object and thus should not be destroyed until the scope calling it calls for its destruction?
Thank you in advance for your help, I didn't sleep well last night because the TA made me turn in work that I knew was bugged and I haven't been able to figure out the problem.
I know that it's a lot of code and this is the longest question I've posted to StackOverflow ever; however, I like sleeping well and I don't think I'll rest soundly until I know what's going wrong.
Why do you use pointers to store the values? Use plain integers instead and you are fine.
At first think about the "too early" destruction:
In your code you actually have two temporaries (if no return value optimization takes place):
The first one is newValue and the second one your rvalue temporary that gets returned by operator+.
After a copy of newValue to the temporary rvalue has been made newValue is destructed (the message you see).
Second problem is: You did not specify a custom copy constructor (think about the rule of three). Hence the rvalue temporary copy has all the pointers to the integers that you freed when destructing newValue.
If you can't use plain integers, then you have to write your own copy constructor that really copies (allocates new integers for the new matrix).
If you can use plain integers, then use them and everything is fine (no need for custom destructor/copy constructor/copy assignment operator)
An example copy constructor:
Matrix::Matrix(const Matrix &other) {
this->rows=other.rows;
this->columns=other.columns;
for (int row = 0; row < rows; ++row) {
for (int column = 0; column < columns; ++column) {
// allocate a new integer with the value
// copied from the other matrix
pMatrixOfInt[row][column] = new int(*other.pMatrixOfInt[row][column]);
}
}
}
I'm new to C++, this is my first week since the upgrade from fortran. Sorry if this is a simple question, but could someone help me with operator overloading. I have written a program which has two classes. One object contains a vector and two scalars, the other class simply contains the first object. In a test implementation of this code I suspect the operator overloading to be at fault. The program tries to accomplish the following goals:
1) Initialize first structure.
2) Initialize a second structure containing the initialized first structure. After this is imported, the value val0 = 10 is added to every element of the vector in the enclosing structure, structure2.structure1 .
3) Output structure1 and structure2 variables to compare.
For this simple program my output is:
100
100
0
0
0 0 10
1 1 11
2 2 12
3 3 13
...
I was expecting:
100
100
0
10
0 0 10
1 1 11
2 2 12
3 3 13
...
Clearly my overloaded = operator is copying my vector properly, but one of the scalars? Could someone help?
#include <iostream>
using namespace std;
typedef double* doublevec;
// This first class contains a vector, a scalar N representing the size of the vector, and another scalar used for intializing the vector.
typedef class Structure1
{
int N, vec0;
doublevec vec;
public:
// Constructor and copy constructor.
Structure1(int Nin, int vecin) : N(Nin), vec0(vecin) { vec = new double [N]; for(int i = 0; i < N; i++) { vec[i] = i + vec0; } }
Structure1(const Structure1& structurein);
// Accessor functions:
int get_vec0() { return vec0; }
int get_N() { return N; }
doublevec get_vec() { return vec; }
// Overide equivalence operator:
Structure1& operator=(const Structure1& right)
{
//Handle Self-Assignment
if (this == &right) return *this;
N = right.N;
vec0 = right.vec0;
for (int i = 0; i < N; i++)
{
vec[i] = right.vec[i];
}
return *this;
}
// Destructor:
~Structure1() { delete []vec; }
} Structure1;
Structure1::Structure1(const Structure1& structurein)
{
N = structurein.N;
vec = new double[N];
for(int i = 0; i < N; i++)
{
vec[i] = structurein.vec[i];
}
}
// This class just contains the first structure.
typedef class Structure2
{
Structure1 structure;
// Mutator Function:
void mutate_structure();
public:
// Constructor:
Structure2(const Structure1& structurein) : structure(structurein) { mutate_structure(); }
// Accessor Function:
Structure1 get_structure() { return structure; }
// Destructor:
~Structure2() {}
} Structure2;
void Structure2::mutate_structure()
{
int N = structure.get_N();
Structure1 tempstruct(N,10);
structure = tempstruct;
}
int main (int argc, char * const argv[])
{
const int N = 100;
Structure1 structure1(N,0);
Structure2 structure2(structure1);
cout << structure1.get_N() << endl;
cout << structure2.get_structure().get_N() << endl;
cout << structure1.get_vec0() << endl;
cout << structure2.get_structure().get_vec0() << endl;
for(int i = 0; i < N; i++)
{
cout << i << " " << structure1.get_vec()[i] << " " << structure2.get_structure().get_vec()[i] << endl;
}
return 0;
}
it looks like vec0 isn't initialized by your copy constructor...
Try modifying your copy constructor to:
Structure1::Structure1(const Structure1& structurein)
{
N = structurein.N;
vec = new double[N];
for (int i = 0; i < N; i++)
{
vec[i] = structurein.vec[i];
}
// ADD THIS LINE
vec0 = structurein.vec0;
}
Your copy-constructor Structure1::Structure1(const Structure1 &) doesn't copy vec0. It's not getting initialised at all, so gets whatever is in memory.
Also, you might want to check Structure1's operator=. If you assign a large vector to a small vector, then you'll potentially overflow the array in the destination. You might need to reallocate memory in operator=.