First off, here is the code:
#include <iostream>
#include <algorithm>
using namespace std;
class Array
{
int* arr;
int n;
public:
Array();
Array(const Array&);
Array(Array &&);
Array& operator=(const Array&);
Array& operator=(Array &&);
void print();
~Array();
};
Array::Array()
{
cout<<"No of elements: "<<endl;
cin>>n;
if(n!=0)
{
arr = new int [n];
cout<<"\nInsert values:"<<endl;
for_each(arr, arr+n, [](int x){cin>>x;});
}
}
Array::Array (const Array& a)
{
int i=0;
this->n=a.n;
arr= new int [n];
for(i=0;i<n;i++)
arr[i]=a.arr[i];
}
Array::Array (Array &&a)
{
this->n=a.n;
arr=a.arr;
a.arr=nullptr;
}
Array& Array::operator=(const Array& a)
{
int i=0;
this->n=a.n;
arr= new int [n];
for(i=0;i<n;i++)
arr[i]=a.arr[i];
return *this;
}
Array& Array::operator=(Array &&a)
{
this->n=a.n;
arr=a.arr;
a.arr=nullptr;
return *this;
}
void Array::print()
{
for_each(arr, arr+n, [](int a){cout<<a;});
}
Array::~Array()
{
n=0;
delete [] arr;
}
int main()
{
Array a;
Array b;
Array c=a;
Array d;
d=b;
c.print();
cout<<endl;
d.print();
return 0;
}
So, as you can see, i made default constructor (if constructor with no parameters can be called default) that creates an array using for_each loop with lambda function used as a third parameter, all it does, as you can see is that it accepts the values i insert and places it as a values of variable x, which should take values from arr[0] to arr[n-1].
However, when i print put any of arrays created in main, it prints out only zeroes, it is not due to copy constructors, because i tried printing arrays a and b and same thing happened (notice that in this case i am printing out c and d, as they are copies of a and b, respectively).
I also tried to see if it works properly as i tried to print out some elements of array right after for_each loop finished, and it turns out that for_each loop has no effect on the array as it stays zero even right after loop.
Any help appreciated!
When you're using for_each loops, you're passing a lambda,
for_each(arr, arr+n, [](int x){cin>>x;});
But the argument of the lambda (int x), mean that you're creating a copy of an array element, that you will assign a value to. That copy will be destroyed when you leave the body of the lambda, while the original value inside the array remains unchanged.
Change it to
for_each(arr, arr+n, [](int& x){cin>>x;});
That way you won't create a copy of the value inside the array, but you'll pass a reference to it, which means you will write the values into the array.
Related
I'm new with c++ and I've been meaning to implement vector calculations via operator overloading.
The code that's not functioning as I intended is this.
First, main.cpp
#include <iostream>
#include "MyVector.h"
#include "MyVector.cpp"
int main() {
double forvector1[] = {0.1,0.2,0.3};
double forvector2[] = {0.2,0.3,0.5};
MyVector vector1(forvector1,3);
MyVector vector2(forvector2,3);
MyVector temp = vector1 + vector2;
temp.print();
return 0;
}
Then, MyVector.cpp
#include "MyVector.h"
#include <iostream>
using namespace std;
MyVector::MyVector(double numList[], int size) : numList(numList), size(size) {
}
MyVector::MyVector(){ //empty vector;
}
void MyVector::print(){
cout<<"("<<numList[0];
for(int i=1;i<size;i++){
cout<<", "<<numList[i];
}
cout<<")"<<endl;
}
MyVector MyVector:: operator+(MyVector vec){
if(vec.size != size){
cout<<"+ cannot be applied to ";
cout<<"("<<numList[0];
for(int i=1;i<size;i++){
cout<<", "<<numList[i];
}
cout<<") and ";
vec.print();
return MyVector();
}
double tempList[size];
for(int i=0;i<size;i++)
{
tempList[i]=numList[i]+vec.numList[i];
}
MyVector result(tempList,size);
return result;
}
Finally, this is my MyVector.h
class MyVector{
private:
int size;
double * numList;
public:
MyVector(double numList[], int size); //size>=1
MyVector(); //empty Vector
void print(); //print its content e.g. (1, 2, 3, 4)
MyVector operator-(MyVector vec);
MyVector operator+(MyVector vec);
double operator*(MyVector vec);
MyVector operator/(MyVector vec);
//You may add more member functions as well
};
#endif // MYVECTOR_H_INCLUDED
According to the main.cpp, I should be getting (0.3, 0.5, 0.8) for the output. However, I keep getting (0.3, 0, 2.12199e-314), which means probably only the first element of the result array was right. I'm guessing it's because of the pointer I used to point at the array, so that's why only the first element was correct. Is there any way I could make the operator+ work? Any help would be appreciated. Thanks!
My guess would be that there is a dangling pointer.
double tempList[size];
for(int i=0;i<size;i++)
{
tempList[i]=numList[i]+vec.numList[i];
}
MyVector result(tempList,size);
return result;
tempList points to data that are local to the function, but result uses it. In your constructor, you should copy the data in the array into another array owned by the object.
Hi I'' trying to make a template for a class to print out values in an array.
#include<iostream>
using namespace std;
template <typename T>
class Array{
public:
Array(T array[], int arraysize){
size=arraysize;
_array=new T[size];
}
~Array(){
delete[] _array;
}
void print(){
for(int i=0; i<size; i++){
cout<<_array[i]<<' ';
}
}
private:
T *_array;
int size;
};
int main(){
int array1[5]={1,2,3,4,5};
Array<int> a(array1,5);
a.print();
float array2[5]={1.012, 2.324, 3.141, 4.221, 5.327};
Array<float> b(array2,5);
b.print();
string array3[]={"Ch1","Ch2","Ch3","Ch4","Ch5"};
Array<string> c(array3,5);
c.print();
return 0;
}
This is the code and I was wondering what's wrong because it would print out random numbers.
The code creates the template's class member _array using new, but does not initialize it to anything, and that's why you get random garbage printed out.
The constructor does receive a parameter array, and an initialized array is passed using that parameter. However, that parameter is completely ignored by the constructor, and nothing is done with it.
Your intent here, obviously, is to copy the contents of the array the template constructor receives, as an argument, into _array. But that code is missing.
The contents of the array parameter will not get copied into _array all by themselves. You have to write the code to do that.
Your constructor:
Array(T array[], int arraysize){
size=arraysize;
_array=new T[size];
}
All you did was to assign the Array's size and allocate memory without actually copying the contents. So all you see some random value for POD types, and default-constructed values for class types.
You should do the copying with std::copy
Array(T array[], int arraysize)
: _array(new T[arraysize]), size(arraysize)
{
std::copy(array, array+arraysize, _array);
}
As you can see, I used member initailizer list; Please remember the Rule of 5. Also, I advise you to use a std::unique_ptr instead.
I am new c++ programmer. I want to create a Matrix class in c++ using dynamic programming. I had a problem with copy constructor. When I call operator + to use it for matrix-addition, the copy constructor throws a bad_alloc-Exception. The problem occurs in the copy-constructor, when i try to create a new dynamic memory, where i can copy my data:
matrix= new int [size];
I don 't understand why.
Here is the whole code: (only the cpp-file)
#include <iostream>
#include "Matrix.hpp"
Matrix::Matrix(int m, int n){
mat_row=m;
mat_col=n;
matrix = new int[mat_row*mat_col];
//initialization
for(int i=0;i<mat_row*mat_col;i++){
matrix[i]=0;
}
}
//copy-Constructor
Matrix::Matrix(const Matrix& mat){
int size=mat_row*mat_col;
matrix= new int [size];
for(int i=0;i<size;i++){
matrix[i]=mat.matrix[i];
}
}
Matrix::~Matrix(){
if(matrix){
delete [] matrix;
}
}
//assigment operator
Matrix& Matrix::operator=(const Matrix& mat){
std::cout<<"assignment-operator is used"<<std::endl;
if(this!=&mat){
int size=mat_row*mat_col;
for(int i=0;i<size;i++){
matrix[i]=mat.matrix[i];
}
}
return *this;
}
void Matrix::set(int m, int n, double value){
if(matrix){
matrix[m*mat_col+n]=value;
}
}
double Matrix::get(int m, int n){
return matrix[m*mat_col+n];
}
Matrix Matrix::operator+(Matrix mat){
/*
Matrix resultMatrix(mat_row, mat_col);
for(int i=0;i<mat_row;i++){
for( int j=0;j<mat_col;j++){
resultMatrix->set(i,j,this->get(i,j)+mat.get(i,j));
}
}
return *this;
*/
}
int main(){
Matrix mat1(3,3);
mat1.set(0,0,11);
mat1.set(1,1,22);
mat1.set(2,2,33);
mat1.print();
std::cout<<std::endl;
Matrix mat2(3,3);
mat2=mat1;
mat2.print();
std::cout<<std::endl;
mat2.set(0,1,55);
mat2.set(1,1,110);
mat2.set(2,2,220);
mat2.print();
mat1+mat2; //the problem occurs when this row will be executed
}
The first thing I noticed is that in your copy constructor mat_row and mat_col are not initialized. They should be getting set from the values that are in the object you are copying before you multiply them together to make size. If you don't do that first then the existing values are undefined and likely very large values, causing the new to fail.
//copy-Constructor
Matrix::Matrix(const Matrix& mat){
mat_row = mat.mat_row;
mat_col = mat.mat_col;
int size=mat_row*mat_col;
matrix= new int [size];
for(int i=0;i<size;i++){
matrix[i]=mat.matrix[i];
}
}
It looks like you have the exact same problem in you operator=() as well.
In the code where you indicate that your problem shows up you do not have an lvalue. You have mat1+mat2; so the result of that addition ends up being unused.
Also, your operator+() should be taking a const ref to the matrix and that is your actual issue. Passing by value like you currently are will cause a temporary copy which is created through the copy constructor.
/This program is using template class. I don't know why but this program is throwing an error at run time related memory access violation. in below comments i will explain which line is causing this error./
#include<iostream>
using namespace std;
const int size =3;
template <class t="">
class vector
{
T* v;
public:
vector()
{
v=new T[size];
for(int i=0;i<size;i++)>
v[i]=0;
}
vector(T* a)
{
for(int i=0;i<size;i++)>
v[i]=a[i];
}
T operator*(vector &y)
{
T sum=0;
for(int i=0;i<size;i++)>
sum+=this->v[i] * y.v[i];
return sum;
}
void display(void)
{
for(int i=0;i<size;i++)>
{
cout<<v[i]<<"\t";
}
cout<<"\n";
}
};
int main()
{
int x[3]={1,2,3};
int y[3]={4,5,6};
vector<int> v1;
vector <int> v2;
v1=x; // This is causing an error
v2=y; // This is causing an error
//int R=v1*v2;
//cout<<"R = "<<R<<"\n";
cout<<"V1 = ";
v1.display();
cout<<"V2 = ";
v2.display();
cout<<"V1 x V2 = "<<v1*v2;
return 0;
}
It seems that the problem is in this constructor
vector(T* a)
{
for(int i=0;i<size;i++)>
v[i]=a[i];
}
You did not allocate memory for the array pointed by v.
2 Problems:
You are not initializing memory for your vector
You are calling the constructor incorrecly
To fix #1
vector(T* a)
{
v=new T[size];
for(int i=0;i<size;i++)>
v[i]=a[i];
}
To fix #2
int x[3]={1,2,3};
int y[3]={4,5,6};
vector<int> v1(x);
vector <int> v2(y);
the constructor vector(T * a) will get called and the member v is not initialized with anything. This causes undefined behavior. So to fix this you need to allocate in that constructor
vector(T* a)
{
v = new T[size];//this line is new
for(int i=0;i<size;i++)
v[i]=a[i];
}
My guess is there is no operator=(int []) defined for vector.
So in other words, compiler does not know what do you mean by v1=x when it comes to type int[] = vector<int>.
You are not calling the overloaded constructor there. So you either need to call it vector<int> v1(y); or implement vector::operator=(const T[] v);
I hope i got the types right
When calling the lines in question, the program is using a default assignment operator which is doing something that causes your violation. You need to implement this yourself, for example, this worked for me:
T& operator=(T const * a)
{
for(int i=0;i<size;i++)
v[i]=a[i];
return *this;
}
I'm trying to create my own version of an array called a safearray, to test my knowledge of operator overloading and creating proper class's and such.
I'm encountering two errors.
SafeArray.h:11:15: error: ‘const int SafeArray::operator’ cannot be overloaded
SafeArray.h:10:10: error: with ‘int& SafeArray::operator’
My code is split between three files.
Main.cpp
#include <cstdlib>
#include <iostream>
#include "SafeArray.h"
using namespace std;
int main(int argc, char** argv) {
SafeArray a(10); // 10 integer elements
for (int i = 0; i < a.length(); i++) {
cout << i << " " << a[i] << "s" << endl; // values initialise to 0
}
cout << endl << a[1]; // Program exits here.
a[3] = 42;
cout << a[3];
a[10] = 10;
cout << a[10];
a[-1] = -1; // out-of-bounds is "safe"?
SafeArray b(20); // another array
b = a; // array assignment
for (int i = 0; i < b.length(); i++) {
cout << b[i] << endl; // values copied from a
}
return 0;
}
SafeArray.h
#ifndef SAFEARRAY_H
#define SAFEARRAY_H
class SafeArray {
public:
SafeArray(int); // int variable will be the array size
int length();
int boundsCheck(int y); // constructor will call this function
// const SafeArray operator= (const SafeArray&);
int& operator[] (int y);
const int operator [] (const int y); // you need this one too.
SafeArray &operator=(SafeArray rhs) {
std::swap(array, rhs.array);
std::swap(length_, rhs.length_);
}
SafeArray(SafeArray const &other);
~SafeArray();
private:
int length_;
int *array;
//int array[];
};
#endif /* SAFEARRAY_H */
SafeArray.cpp
#include "SafeArray.h"
#include <iostream>
SafeArray::SafeArray(int x) {
length_ = x;
array = new int[length];
for (int i = 0; i < length_; i++) {
array[i] = 0;
}
}
int SafeArray::length() {
return this->length_;
}
int SafeArray::boundsCheck(int y) {
}
int& SafeArray::operator[] (int y) {
return array[y];
}
SafeArray::~SafeArray() {
delete [] array;
}
SafeArray::SafeArray(SafeArray const &other) {
int *temp = new int[rhs.size_];
for (int i=0; i<rhs.size_; i++)
temp[i] = rhs.array[i];
std::swap(temp, array);
delete [] temp;
return *this;
}
Your class definition isn't valid. int array[] is an incomplete type, which must not appear as a (non-static) class member. Some compilers accept this as a synonym for int array[0], but zero-sized arrays are not valid in C++, either (only in C99).
In short, you cannot write your code the way you do. You need to learn about dynamic allocation and manage your own memory. Check out how std::vector is implemented.
In C++11, I might recommend a std::unique_ptr<int[]> array as a quick-fix approach, to be initialized as array(new int[x]).
Actually int array[] is valid, and may appear as a class member. The following compiles with strict C++11 conformance:
class foo
{
public:
foo() {}
int length;
int A[];
};
void ralph()
{
foo *bar = (foo *)new int[ 21 ];
bar->length = 20;
bar->A[0] = 1;
}
This is legal, and has its advantages (occasionally). Although it is not commonly used.
However, I suspect that the OP wanted something more along the lines of
class SafeArray {
public:
SafeArray(int); // int variable will be the array size
int length();
int boundsCheck(int y); // constructor will call this function
int& operator[] (int y);
const int operator [] (const int y) // you need this one too.
private:
int length_;
int *array;
};
along with
SafeArray::SafeArray(int x) {
length_ = x;
array = new int[length];
for (int i = 0; i < length_; i++) {
array[i] = 0;
}
}
As #Kerrek already pointed out, your class definition is clearly wrong (shouldn't compile).
To fix it, you want to change the definition to something like:
int *array;
Then in your default ctor you could use something like this:
SafeArray::SafeArray(unsigned size = 0)
: array(new int[size])
{
for (unsigned i=0; i<size; i++)
array[i] = 0;
}
Then, yes, you'll need to write an assignment operator. The usual way is called the copy and swap idiom. You create a copy, then swap the contents of the current one with those of the copy:
SafeArray &operator=(SafeArray rhs) {
std::swap(array, rhs.array);
std::swap(length_, rhs.length_);
}
Along with that, you'll need a copy constructor that makes a copy of the data as well:
SafeArray::SafeArray(SafeArray const &other) {
int *temp = new int[rhs.size_];
for (int i=0; i<rhs.size_; i++)
temp[i] = rhs.array[i];
std::swap(temp, array);
delete [] temp;
return *this;
}
Finally, you'll need a destructor to destroy an object and (particularly) delete the memory it holds:
SafeArray::~SafeArray() {
delete [] array;
}
Then realize that all of that is an ugly mess that will never really work well. In particular, the basic methodology is restricted to an array that's basically fixed in size. As long as you only store ints, it's fairly easy to overlook the problems, and make a dynamic array that (sort of) works. When/if you want to store some other type, however, you just about need to separate allocating memory from initializing objects in that memory, which means throwing away essentially all the code above, and replacing it with something that:
keeps track of the array size and allocation size separately
allocates memory with ::operator new, an Allocator object, or something else similar
uses placement new to initialize objects in the memory when needed.
uses explicit destructor calls to destroy the objects
uses ::operator delete to release memory
and so on. To summarize, std::vector is not a trivial piece of work.
The error message refers to these two lines:
int& operator[] (int y);
const int operator [] (const int y); // you need this one too.
Your error message says that (int y) and (const int y) are too similar to be two different overloads of the [] operator. You cannot overload on (int y) and (const int y) because the calls would all be ambiguous.
You probably meant to return a const int if your SafeArray is const, but return an int& if your SafeArray is not const. In that case, you declare the second function to apply to const SafeArray, by putting the word const after the parameter list. This is what you should write in SafeArray.h:
int& operator[] (int y);
const int operator [] (int y) const; // you need this one too.
You would then have to write both of these functions in SafeArray.cpp:
int& SafeArray::operator[] (int y) {
return array[y];
}
const int SafeArray::operator[] (int y) const { // you need this one too.
return array[y];
}