I got a class Vectors which has private dynamic array.
All I wanted to do is to add two Vectors objects like A = A + B, but the program keeps crashing.
This is declaration of my class:
class Vectors
{
private:
int* vector;
public:
Vectors(int);
Vectors(Vectors&);
~Vectors();
Vectors operator+(Vectors&);
};
This is my implementation:
#include "Vectors.h"
#include "iostream"
using namespace std;
Vectors::Vectors(int value)
{
this->vector = new int[3];
for (auto i = 0; i < 3; i++)
{
vector[i] = 3;
}
}
Vectors::Vectors(Vectorsy& copy)
{
this->vector = new int[3];
for (auto i = 0; i < 3; i++)
{
vector[i] = copy.vector[i];
}
}
Vectors::~Vectors()
{
delete[] vector;
}
Vectors Vectors::operator+(Vectors& obj) // There is sth wrong here.
{
for (auto i = 0; i < 3; i++)
this->vector[i] += obj.vector[i];
return *this;
}
This is the error I get:
I believe you need an operator= function. You haven't implemented it so the compiler writes a default one which does the wrong thing (due to the fact that the class has a pointer). Most likely the crash is occurring while deleting the same memory twice.
See What is The Rule of Three?
The problem was the copy Constructor (Vectors::Vectors(const Vectors& copy)
Hear a working code.
#include "iostream"
using namespace std;
class Vectors
{
private:
int* vector;
public:
Vectors(int);
Vectors(const Vectors&);
~Vectors();
Vectors operator+(Vectors&);
};
Vectors::Vectors(int value)
{
this->vector = new int[3];
for (auto i = 0; i < 3; i++)
{
vector[i] = 3;
}
}
Vectors::Vectors(const Vectors& copy)
{
this->vector = new int[3];
for (auto i = 0; i < 3; i++)
{
vector[i] = copy.vector[i];
}
}
Vectors::~Vectors()
{
delete[] vector;
}
Vectors Vectors::operator+(Vectors& obj) // There is sth wrong here.
{
for (auto i = 0; i < 3; i++)
this->vector[i] += obj.vector[i];
return *this;
}
int main()
{
Vectors A(3), B(3);
Vectors C = A+B;
}
Related
Having trouble with the printing copy constructors elements from Arr s to Arr s1 , also having troubles with << operator it doesn't work, please help cuz I am not pro just a student.
#include <iostream>
using namespace std;
class Arr {
private:
int size;
int *arr;
public:
Arr(int size,int *arr) {
this->size = size;
this->arr = new int [size];
for (int i = 0; i < size ; ++i) {
this->arr[i] = arr[i];
}
}
~Arr() {
delete[] arr;
}
Arr(const Arr &x) {
this->size = x.size;
this->arr = new int[x.size];
for (int i = 0; i < x.size; ++i) {
this->arr = x.arr;
}
}
Arr() : size(0),arr(0) {}
Arr(Arr &&x) {
this->size = x.size;
this->arr = new int[x.size];
for (int i = 0; i < x.size; ++i) {
this->arr = x.arr;
}
}
friend ostream &operator<<(ostream &out, const Arr &t) {
out << t.size;
for (int i = 0; i < t.size; i++) {
out << t.arr[i];
}
return out;
}
friend istream &operator>>(istream &in, Arr &t) {
in >> t.size;
for (int i = 0; i < t.size; ++i) {
in >> t.arr[i];
}
return in;
}
};
int main() {
int size = 3;
int arr [] = {1,2,3};
Arr s1(size,arr);
cin << s1;
cout<<s1;
Arr s(s1);
cout<<s; // not working at all
return 0;
}
You are writing
this->arr = x.arr;
in the copy constructor, rather than
this->arr[i] = x.arr[i];
That is, currently your code is copying the array pointer, not the elements of the array.
When you're debugging, first look over your code to make sure each part is doing what you want it to do and that you didn't make a typo like this. Then, if you don't find the problem, you can use a debugger like gdb to step through your code and monitor the values of the variables to make sure your program is doing what you'd like.
I simulated a vector but the constructor doesn't work; when I call pop() function it assigns garbage value to my old object in vector class.
vector(vector &v) {
vec = new T[v.size()];
memcpy(vec, v,v.size());
size_arr = v.size();
}
here's entire code:
#include <iostream>
using namespace std;
template <typename T>
class vector {
int size_arr;
T * vec = new T;
public:
vector(/*int _size*/) {
vec = new T[0];
size_arr = 0;
};
~vector() {
size_arr = 0;
delete[] vec;
};
vector(vector &v) {
vec = new T[v.size()];
memcpy(vec, v,v.size());
size_arr = v.size();
}
void push_back(T data) {
T *temp = new T[size_arr + 1];
for (int i = 0; i < size_arr; i++)
temp[i] = vec[i];
temp[size_arr] = data;
size_arr++;
delete[] vec;
vec = temp;
};
void push_front(T data){
int j;
T *temp = new T[size_arr + 1];
for ( j = size_arr; j >= 0;j--) {
temp[j + 1] = vec[j];
}
temp[0] = data;
delete[] vec;
vec = temp;
size_arr++;
};
void insert(int index, T data) {
int j;
T *temp = new T[size_arr + 1];
for (int i = 0; i < size_arr ;i++)
temp[i] = vec[i];
for (int i = 0; i < size_arr;i++) {
if (i == index) {
for ( j = size_arr; j >=i;j--) {
temp[j+1] = vec[j];
}
temp[j + 1] = data;
delete[] vec;
vec = temp;
size_arr++;
}
}
};
void pop() {
T *temp = new T[size_arr - 1];
for (int i = 0; i < size_arr-1;i++)
temp[i] = vec[i];
size_arr--;
delete[] vec;
vec = temp;
};
void Delete(int index)
{
T *temp = new T[size_arr - 1];
for (int i = 0; i < index;i++)
temp[i] = vec[i];
for (int i = 0; i < size_arr;i++) {
if (i == index) {
for (int j = i; j < size_arr-1;j++) {
temp[j] = vec[j + 1];
}
size_arr--;
delete[] vec;
vec = temp;
}
}
};
int search(T data) {
for (int i = 0; i < size_arr;i++) {
if (vec[i] == data) {
return i;
}
}
return -1;
};
int size() { return size_arr; };
};
int main() {
vector <int>test;
test.push_front(2);
test.push_front(3);
test.push_back(0);
test.push_back(-1);
test.insert(2, 2);
test.pop();
vector <int > test1;
test1 = test;// problem
test1.pop();
}
The problem is the line test1 = test;// problem, which does not call the copy constructor, but the assignment operator. You did not declare this operator, so the compiler will use the default implementation, which simply copies all member. So, after the assignment test1.vec and test.vec point to the same memory location.
When you change the line (and the one above it) to vector <int > test1{test};, it will call your copy constructor.
You also forgot to #include <cstring> for memcpy, which you should not use for non-POD types.
You have to multiply the size in memcpy with sizeof(T), because memcpy works on bytes, not on types. You also have to use v.vec instead of v.
Here is the fixed version: https://ideone.com/JMn7ww
I think the problem is in your copy operator. You use memcpy() which is a c function. Which should in itself not be a problem (apart from it being not so nice in many opinions). But since memcpy() is a c function, it doesn't know about types, and it takes its size arguments as a count of bytes.
the element you put in is int which is probably 4 bytes. So when your copy contstructor gets called, and the original has 3 elements, there will be 12 bytes in your array, but malloc will only copy 3 of them.
The comments of other people about not properly copying template types are right, so if you make a vector of strings, you cannot just memcpy them, and assume the result will be new strings. For this answer i was assuming you using only basic types as your template arguments like int, or double.
For the following mymatrix class definition, why don't I need the commented parts of the destructor? Don't we need to delete what the a pointer points to as well? Or is it because we deleted all the meaningful data that we don't need these (commented-out) parts of the destructor?
template<typename T>
class mymatrix
{
private:
struct ROW
{
T* Cols; // dynamic array of column elements
int NumCols; // total # of columns (0..NumCols-1)
};
ROW* Rows; // dynamic array of ROWs
int NumRows; // total # of rows (0..NumRows-1)
}
Destructor:
virtual ~mymatrix()
{
for(int r=0;r<numRows;r++)
{
for(int c=0;c<Rows[r].NumCols;c++)
{
delete Rows[r].Cols[c];
}
// delete Rows[r];
}
// delete Rows;
}
Constructor:
mymatrix(int R, int C)
{
if (R < 1)
throw invalid_argument("mymatrix::constructor: # of rows");
if (C < 1)
throw invalid_argument("mymatrix::constructor: # of cols");
Rows = new ROW[R]; // an array with R ROW structs:
NumRows = R;
//intialize each row to C columns
for(int r=0;r<R;r++){
Rows[r].Cols=new T[C];
Rows[r].NumCols=C;
//initialize elements to their default value
for(int c=0;c<Rows[r].NumCols;c++){
Rows[r].Cols[c]=T{}; // default value for type T;
}
}
}
You need to use array-delete syntax because you are deleting arrays, not single objects:
delete[] Rows[r].Cols
...
delete[] Rows
Edit: I originally simply included the correct delete[] operator usage and left everything unchanged in my original example for brevity, but as #idclev463035818 pointed out, whenever you define your own destructor, copy constructor, or copy assignment operator (especially when they involve dynamic memory allocation), you almost always need to have all three. Almost never do you want any one without the others because if you have raw pointers in your object, then they will be shallow-copied to the new objects being instantiated. Then later on, the destructors for each of these objects will be called and attempt to delete the same portions of memory multiple times, which is a major error. I've added these to the code example and make use of them in new tests in the main function.
Full code:
#include <iostream>
using namespace std;
template<typename T>
class mymatrix
{
public:
struct ROW
{
T* Cols; // dynamic array of column elements
int NumCols; // total # of columns (0..NumCols-1)
};
ROW* Rows; // dynamic array of ROWs
int NumRows; // total # of rows (0..NumRows-1)
public:
mymatrix(int R, int C)
{
init(R, C);
}
void init(int R, int C) {
if (R < 1)
throw "";//throw invalid_argument("mymatrix::constructor: # of rows");
if (C < 1)
throw "";//invalid_argument("mymatrix::constructor: # of cols");
Rows = new ROW[R]; // an array with R ROW structs:
NumRows = R;
//intialize each row to C columns
for (int r = 0; r < R; r++) {
Rows[r].Cols = new T[C];
Rows[r].NumCols = C;
//initialize elements to their default value
for (int c = 0; c < Rows[r].NumCols; c++) {
Rows[r].Cols[c] = T{}; // default value for type T;
}
}
}
mymatrix(const mymatrix& other) : mymatrix(other.NumRows, other.Rows[0].NumCols) {
for (int r = 0; r < NumRows; ++r) {
ROW& thisRow = Rows[r];
ROW& otherRow = other.Rows[r];
for (int c = 0; c < thisRow.NumCols; ++c) {
thisRow.Cols[c] = otherRow.Cols[c];
}
}
}
mymatrix& operator=(const mymatrix& other) {
if (other.NumRows != NumRows || other.Rows[0].NumCols != Rows[0].NumCols) {
clear();
init(other.NumRows, other.Rows[0].NumCols);
}
for (int r = 0; r < NumRows; ++r) {
ROW& thisRow = Rows[r];
ROW& otherRow = other.Rows[r];
for (int c = 0; c < thisRow.NumCols; ++c) {
thisRow.Cols[c] = otherRow.Cols[c];
}
}
return *this;
}
void clear() {
for (int r = 0; r < NumRows; r++)
{
delete[] Rows[r].Cols;
}
delete[] Rows;
Rows = NULL;
NumRows = 0;
}
virtual ~mymatrix()
{
clear();
}
};
int main() {
mymatrix<int> mat(5, 5);
mat.Rows[0].Cols[2] = 5;
mymatrix<int> matClone(mat);
cout << matClone.Rows[0].Cols[2] << endl;
matClone.Rows[0].Cols[1] = 8;
cout << mat.Rows[0].Cols[1] << endl;
mat = matClone;
cout << mat.Rows[0].Cols[1] << endl;
system("pause");
return 0;
}
I'm telling this every time I see the usage of new/delete in C++.
Please don't use new/delete in C++!
Here is a minimal example of how to create a matrix which will allocate and delete itself without any manual memory allocations.
#include <vector>
class Matrix : public std::vector<std::vector<int>> {
public:
Matrix(size_t numRows, size_t numCols)
: std::vector<std::vector<int>>(numRows, std::vector<int>(numCols, 0)) {}
size_t numRows() const { return size(); }
size_t numCols() const { return front().size(); }
};
int main() {
auto m = Matrix(5, 4);
return m[4][3];
}
This is simple program that is supposed to handle a dynamic array of numbers and then to filter out the elements that are even and put them into a new array and then print both arrays on the screen.
This is the header file:
#pragma once
namespace filter
{
class Array
{
double *arr;
int n;
public:
Array();
Array(int);
Array(const Array&);
Array(Array&&);
void PutIn();
void PrintOut() const;
Array isEven();
Array filter(const std::function<bool(int)>&) const;
~Array();
};
}
Then, this is the implementation of functions:
#include <iostream>
#include <functional>
#include "Array.h";
using namespace filter;
using namespace std;
Array::Array() :arr(nullptr), n(0)
{ }
Array::Array(int n)
{
this->n = n;
arr = new double[n];
}
Array::Array(const Array &a1)
{
n = a1.n;
arr = new double[n];
for (int i = 0; i < n; i++)
arr[i] = a1.arr[i];
}
Array::Array(Array &&a1)
{
n = a1.n;
for (int i = 0; i < n; i++)
arr[i] = a1.arr[i];
a1.n = 0;
a1.arr = nullptr;
}
void Array::PutIn()
{
cout << "Insert elements:\n";
for (int i = 0; i < n; i++)
cin >> arr[i];
}
void Array::PrintOut() const
{
cout << "\nYour array is :\n";
for (int i = 0; i < n; i++)
cout << arr[i] << "\t";
}
Array Array::isEven()
{
return filter([](int x) { return x % 2; });
}
Array Array::filter(const std::function<bool(int)> &f) const
{
int b = 0;
for (int i = 0; i < n; i++)
if (f(arr[i]) == 0)
b++;
Array temp(b);
b = 0;
for (int i = 0; i < n; i++)
if (f(arr[i]) == 0)
{
temp.arr[b] = arr[i];
b++;
}
return temp;
}
Array::~Array()
{
delete[]arr;
n = 0;
}
Finally, this is the source code:
#include <iostream>
#include <functional>
#include "Array.h"
using namespace filter;
using namespace std;
int main()
{
Array a(5);
a.PutIn();
Array b = a.isEven(); //WHY THIS LINE OF CODE INVOKES MOVE CONSTRUCTOR AND NOT COPY CONSTRUCTOR?
a.PrintOut();
b.PrintOut();
getchar();
getchar();
}
So, as you can see, this is relatively simple program that needs to handle an array with five elements in it entered by user and then to create a new array that consists of even elements of the first array. When i run this, it works fine, however, there is one little thing that i don't understand here.
If you look at the source code, notice the line where i left my comment, that is the line where move constructor is called, but i don't know why. That would mean that a.IsEven() is a RVALUE, since move constructor works with RVALUES, right? Can anyone explain me why this is rvalue and what is the correct way to understand this? Any help appreciated!
Your assumption that calling isEven invokes your move constructor is not in fact correct. Nor does it invoke your copy constructor. Instead, RVO ensures that the object returned is constructed directly at the calling site so neither is required.
Live Demo (which doesn't address any of the flaws in your code mentioned in the comments).
Assume I have a class A that has say 3 methods. So the first methods assigns some values to the first array and the rest of the methods in order modify what is computed by the previous method. Since I wanted to avoid designing the methods that return an array (pointer to local variable) I picked 3 data member and store the intermediate result in each of them. Please note that this simple code is used for illustration.
class A
{
public: // for now how the class members should be accessed isn't important
int * a, *b, *c;
A(int size)
{
a = new int [size];
b = new int [size];
c = new int [size];
}
void func_a()
{
int j = 1;
for int(i = 0; i < size; i++)
a[i] = j++; // assign different values
}
void func_b()
{
int k = 6;
for (int i = 0; i < size; i++)
b[i] = a[i] * (k++);
}
void func_c()
{
int p = 6;
for int (i = 0; i < size; i++)
c[i] = b[i] * (p++);
}
};
Clearly, if I have more methods I have to have more data members.
** I'd like to know how I can re-design the class (having methods that return some values and) at the same time, the class does not have the any of two issues (returning pointers and have many data member to store the intermediate values)
There are two possibilities. If you want each function to return a new array of values, you can write the following:
std::vector<int> func_a(std::vector<int> vec){
int j = 1;
for (auto& e : vec) {
e = j++;
}
return vec;
}
std::vector<int> func_b(std::vector<int> vec){
int j = 6;
for (auto& e : vec) {
e *= j++;
}
return vec;
}
std::vector<int> func_c(std::vector<int> vec){
//same as func_b
}
int main() {
std::vector<int> vec(10);
auto a=func_a(vec);
auto b=func_b(a);
auto c=func_c(b);
//or in one line
auto r = func_c(func_b(func_a(std::vector<int>(10))));
}
Or you can apply each function to the same vector:
void apply_func_a(std::vector<int>& vec){
int j = 1;
for (auto& e : vec) {
e = j++;
}
}
void apply_func_b(std::vector<int>& vec){
int j = 6;
for (auto& e : vec) {
e *= j++;
}
}
void apply_func_c(std::vector<int>& vec){
// same as apply_func_b
}
int main() {
std::vector<int> vec(10);
apply_func_a(vec);
apply_func_b(vec);
apply_func_c(vec);
}
I'm not a big fan of the third version (passing the input parameter as the output):
std::vector<int>& func_a(std::vector<int>& vec)
Most importantly, try to avoid C-style arrays and use std::vector or std::array, and don't use new, but std::make_unique and std::make_shared
I'm assuming you want to be able to modify a single array with no class-level attributes and without returning any pointers. Your above code can be modified to be a single function, but I've kept it as 3 to more closely match your code.
void func_a(int[] arr, int size){
for(int i = 0; i < size; i++)
arr[i] = i+1;
}
void func_b(int[] arr, int size){
int k = 6;
for(int i = 0; i < size; i++)
arr[i] *= (k+i);
}
//this function is exactly like func_b so it is really unnecessary
void func_c(int[] arr, int size){
int p = 6;
for(int i = 0; i < size; i++)
arr[i] *= (p+i);
}
But if you just want a single function:
void func(int[] arr, int size){
int j = 6;
for(int i = 0; i < size; i++)
arr[i] = (i+1) * (j+i) * (j+i);
}
This solution in other answers is better, if you are going to allocate memory then do it like this (and test it!) also if you are not using the default constructor and copy constructor then hide them, this will prevent calling them by accident
class A{
private:
A(const &A){}
A() {}//either define these or hide them as private
public:
int * a, *b, *c;
int size;
A(int sz) {
size = sz;
a = new int[size];
b = new int[size];
c = new int[size];
}
~A()
{
delete[]a;
delete[]b;
delete[]c;
}
//...
};