im trying to make memory pool class and have to overload operator[], but theres a huge(2x) slow down:
T(overloaded) = 76.4043 ns
T(not-ovld) = 28.6016 ns
is it normal or im doing something wrong? thanks for help :)
compiler vc++2013
optimization disabled/full - same thing
class(main.cpp):
template<class T>
class pool{
public:
T *cell;
size_t size = 0;
public:
pool(const size_t n ){
size = n;
cell = new T[size];
}
T& operator [](const size_t i) { return cell[i]; }
T operator [](const size_t i)const { return cell[i]; }
};
main(main.cpp):
template<class T>
T F( T x){
return x/2 % 100;
}
#define test_count 10000000
int main()
{
pool<unsigned int> P(test_count);
unsigned int sum = 0;
resettimer();
// test 1
for (int i = 0; i < test_count; i++)
P[i] = F(i);
for (int i = 0; i < test_count; i++)
sum = sum + P[i];
cout << sum << endl;
//
printtimer();
sum = 0;
resettimer();
// test2
for (int i = 0; i < test_count; i++)
P.cell[i] = F(i);
for (int i = 0; i < test_count; i++)
sum = sum + P.cell[i];
cout << sum << endl;
//
printtimer();
int q;
cin >> q;
return 0;
}
Problem was with Debug build, in Release build (optimization n stuff) all works like it should. Hehe stupid mistake but taught me something :)
Conclusion - dont measure performence in debug mode ;)
Related
so I wrote this code:
#include <iostream>
constexpr
int fibonacci (int n) {
int a = 0;
int b = 1;
for(auto i = 0; i < n; i++) {
b += a;
a = b - a;
}
return b;
}
template<int N, int (T)(int)>
struct array {
using type = decltype(T(0));
constexpr array() : arr() {
for (auto i = 0; i < N; ++i) {
arr[i] = T(i);
}
}
const type &operator[](int i) const { return arr[i]; }
private:
type arr[N];
};
int main() {
constexpr auto x = array<10, fibonacci>();
for (int i = 0; i < 11; i++) {
std::cout << i << " " << x[i] << std::endl;
}
}
And without optimizations it works as expected, prints 11 values with last one being random value. But as soon I move to -O2 I get randomly long list of numbers finished with crash and segmentation fault.
I checked this result on godbolt.org (https://godbolt.org/z/4MqjbPbxE) and it seems that it is not a problem in, for example, clang.
My question is, is this a bug in gcc? Why would optimizations remove/not check condition in for loop?
You are invoking undefined behavior by using out-of-range x[i].
Allocate one more to avoid out-of-range access.
In other words,
constexpr auto x = array<10, fibonacci>();
should be
constexpr auto x = array<11, fibonacci>();
Defining constant to avoid typo is better:
int main() {
constexpr int num = 11;
constexpr auto x = array<num, fibonacci>();
for (int i = 0; i < num; i++) {
std::cout << i << " " << x[i] << std::endl;
}
}
Fix checking index.
for (int i = 0; i < 10; i++) {
This project I am writing in order to create a Square Matrix ADT object has a problem with the constructor (not the default constructor). I have traced the problem back to the constructor but I cannot figure out what is wrong with it which makes it crash everytime I try to run my test in main.cpp.
I usually get an error that say something along the lines "Thread 1: EXC_BAD_ACCESS: ..." and the console usually says "(11db)"
Does anyone have any ideas on what might be causing all the problems?
This is the header file:
#include <iostream>
#include <vector>
using namespace std;
#ifndef SquareMatrix_h
#define SquareMatrix_h
class SquareMatrix {
private:
vector<vector<double>> numMatrix;
public:
SquareMatrix();
SquareMatrix(vector<vector<double>>& v2d);
double getValue(int x, int y);
void setValue(int x, int y, double value);
friend SquareMatrix operator * (SquareMatrix m1, SquareMatrix m2);
friend SquareMatrix operator - (SquareMatrix m1, SquareMatrix m2);
friend ostream& operator <<(ostream &out, SquareMatrix m);
};
#endif /* SquareMatrix_h */
This is my SquareMatrix.cpp file: (The constructor that I believe isn't working is the second function in the code: SquareMatrix::SquareMatrix(vector>& v2d) {...)
#include "SquareMatrix.h"
#include <iostream>
using namespace std;
SquareMatrix::SquareMatrix() {
numMatrix.clear();
for(int i = 0; i < 10; i++) {
vector<double> initial;
for(int j = 0; j < 10; j++) {
initial.push_back(0.0);
}
numMatrix.push_back(initial);
}
}
SquareMatrix::SquareMatrix(vector<vector<double>>& v2d) {
bool flagSize = true;
for(int i = 0; i < v2d.size(); i++) {
if(v2d[i].size() != v2d.size()) {
flagSize = false;
break;
}
}
if(flagSize) {
numMatrix.clear();
for(int i = 0; i < v2d.size(); i++) {
vector<double> initial;
for(int j = 0; j < v2d[i].size(); i++) {
initial.push_back(v2d[i][j]);
}
numMatrix.push_back(initial);
}
} else {
numMatrix.clear();
for(int i = 0; i < 10; i++) {
vector<double> initial;
for(int j = 0; j < 10; j++) {
initial.push_back(0.0);
}
numMatrix.push_back(initial);
}
}
}
double SquareMatrix::getValue(int x, int y) {
if((x < numMatrix.size()) && (y < numMatrix.size()) && (x >= 0) && (y >= 0)) {
return numMatrix[x][y];
}
return 0;
}
void SquareMatrix::setValue(int x, int y, double value) {
if((x < numMatrix.size()) && (y < numMatrix.size()) && (x >= 0) && (y >= 0)) {
numMatrix[x][y] = value;
}
}
SquareMatrix operator * (SquareMatrix m1, SquareMatrix m2) {
if(m1.numMatrix.size() == m2.numMatrix.size()) {
vector<vector<double>> result;
for(int i = 0; i < m1.numMatrix.size(); i++) {
vector<double> initial;
for(int j = 0; j < m1.numMatrix.size(); j++) {
initial.push_back(0);
}
result.push_back(initial);
}
for(int i = 0; i < m1.numMatrix.size(); i++) {
for(int j = 0; j < m1.numMatrix.size(); j++) {
result[i][j] = 0;
for (int a = 0; a < m1.numMatrix.size(); a++) {
result[i][j] += m1.numMatrix[i][a] + m2.numMatrix[a][j];
}
}
}
return SquareMatrix(result);
}
return SquareMatrix();
}
SquareMatrix operator - (SquareMatrix m1, SquareMatrix m2) {
if(m1.numMatrix.size() == m2.numMatrix.size()) {
vector<vector<double>> result;
for(int i = 0; i < m1.numMatrix.size(); i++) {
vector<double> initial;
for(int j = 0; j < m1.numMatrix[i].size(); j++) {
double pushNum = (m1.getValue(i,j) - m2.getValue(i,j));
initial.push_back(pushNum);
}
result.push_back(initial);
}
return SquareMatrix(result);
}
return SquareMatrix();
}
ostream& operator << (ostream &out, SquareMatrix m) {
out << "(";
for (int i = 0; i < m.numMatrix.size(); i++) {
for (int j = 0; j < m.numMatrix.size(); j++) {
out << " " << m.numMatrix[i][j];
if(j != (m.numMatrix.size() - 1)) {
out << ", ";
}
}
}
out << ")";
return out;
}
Then this is the main.cpp that I am using to test the SquareMatrix ADT object:
#include "SquareMatrix.h"
#include <iostream>
#include <random>
#include <ctime>
#include <vector>
using namespace std;
int main() {
srand(time(NULL));
vector<vector<double>> m1;
vector<vector<double>> m2;
int size = 0;
cout << "Enter the size of the Square Matrix: ";
cin >> size;
for (int i = 0; i < size; i++) {
vector<double> in1;
vector<double> in2;
for (int j = 0; j < size; j++) {
in1.push_back(rand() % 100);
in2.push_back(rand() % 100);
}
m1.push_back(in1);
m2.push_back(in2);
}
SquareMatrix res1 = SquareMatrix(m1);
SquareMatrix res2 = SquareMatrix(m2);
cout<< "\nMatrix 1: " << endl;
cout << res1 << endl;
cout<< "\nMatrix 2: " << endl;
cout << res2 << endl;
SquareMatrix mult = res1*res2;
cout << "\nMatrix1 * Matrix 2: " << endl;
cout << mult << endl;
SquareMatrix min1_2 = res1 - res2;
cout << "Matrix1 - Matrix 2: " << endl;
cout << min1_2 << endl;
SquareMatrix min2_1 = res2 - res1;
cout << "Matrix2 - Matrix 1: " << endl;
cout << min2_1 << endl;
return 0;
}
Any help you could give would be appreciated. :)
As pointed out in the comments, you problem is a simple typo in one of your nested loops. However, I'd like to add some recommendations to make your code less error prone (and also more readable).
Firstly, when iterating over all elements of a vector, unless you need an index for something else, you should be using a range-based for-loop. In your code, you might replace the check for square size with the following:
for (const vector<double>& vec: v2d){
if (vec.size() != v2d.size()){
flagSize = false;
break;
}
}
This expresses your intent a little more clearly, and, more importantly, prevents you from accidentally reading from/writing to a location out of your vector's bounds (accidentally typing <= instead of just < happens to the best of us).
Secondly, the two nested loops (that contained your error) can be replaced with a simple copy assignment (numMatrix = v2d; reference). Again, this expresses your intent in addition to being a whole lot shorter. No need to reinvent the wheel with functions like these.
The contents of the else-branch of the surrounding if-statement can also be replaced with a call to assign (the first overload listed on the page, use like numMatrix.assign(10, vector<double>(10, 0.0))). Like before, clearer expression of intent and avoidance of index errors.
Finally, the parameter in this constructor can be a const reference instead of a normal one since you do not alter its contents in any way (and, given this, it should be const).
You might wonder why "expression of intent" is relevant, or what it even means in this context. Essentially, it's all about making what you're trying to do immediately obvious to any reader. This is more important in large projects with many contributors but it is helpful even when debugging small applications like this one. You seem to be learning still, but I strongly believe it's a good thing to keep in mind from the beginning. After all, many of these changes also make for briefer code, making it that much easier for others to help you if you run into a problem.
I realize this left the scope of the original question somewhat, but I hope you find this helpful nonetheless.
I have a 2D array and I want to define a function that returns the value of the index that the user gives me using operator overloading.
In other words:
void MyMatrix::ReturnValue()
{
int row = 0, col = 0;
cout << "Return Value From the last Matrix" << endl;
cout << "----------------------------------" << endl;
cout << "Please Enter the index: [" << row << "][" << col << "] =" << ((*this).matrix)[row][col] << endl;
}
The operation ((*this).matrix)[row][col] should return an int.
I have no idea how to build the operator [][].
Alternatively, I could concatenate a couple of calls to the operator [], but I didn't succeed in it, because the first call to that operaror will return int* and the second one will return int, and it compel to build another operator, and I dont want to do that.
The data matrix is defined like
int** matrix; matrix = new int*[row];
if (matrix == NULL)
{
cout << "Allocation memory - Failed";
}
for (int i = 0; i < row; i++)//Allocation memory
{
matrix[i] = new int[col];
if (matrix[i] == NULL)
{
cout << "Allocation memory - Failed";
return;
}
}
What can I do?
Thank you,
Simply, such an operator does not exist, so you can not overload it.
A possible solution is to define two classes: the Matrix and the Row.
You can define the operator[] of a Matrix so that it returns a Row, then define the same operator for the Row so that it returns an actual value (int or whatever you want, your Matrix could be also a template).
This way, the statement myMatrix[row][col] will be legal and meaningful.
The same can be done in order to assign a new Row to a Matrix or to change a value in a Row.
* EDIT *
As suggested in the comments, also you should take in consideration to use operator() instead of operator[] for such a case.
This way, there wouldn't be anymore the need for a Row class too.
You can define your own operator [] for the class. A straightforward approach can look the following way
#include <iostream>
#include <iomanip>
struct A
{
enum { Rows = 3, Cols = 4 };
int matrix[Rows][Cols];
int ( & operator []( size_t i ) )[Cols]
{
return matrix[i];
}
};
int main()
{
A a;
for ( size_t i = 0; i < a.Rows; i++ )
{
for ( size_t j = 0; j < a.Cols; j++ ) a[i][j] = a.Cols * i + j;
}
for ( size_t i = 0; i < a.Rows; i++ )
{
for ( size_t j = 0; j < a.Cols; j++ ) std::cout << std::setw( 2 ) << a[i][j] << ' ';
std::cout << std::endl;
}
}
The program output is
0 1 2 3
4 5 6 7
8 9 10 11
I have no idea how to build the operator [][].
Sometimes it is fine to use a different operator, namely ():
int& Matrix::operator () (int x, int y)
{
return matrix[x][y];
}
const int& Matrix::operator () (int x, int y) const
{
return matrix[x][y];
}
int diagonal (const Matrix& m, int x)
{
return m (x, x); // Usage.
}
Advantage:
No need to use "intermediate" class like Row or Column.
Better control than with Row& Matrix operator (int); where someone could use the Row reference to drop in a row of, say, illegal length. If Matrix should represent a rectangular thing (image, matrix in Algebra) that's a potential source of error.
Might be less tedious in higher dimensions, because operator[] needs classes for all lower dimensions.
Disadvantage:
Uncommon, different syntax.
No more easy replacement of complete rows / columns, if that's desired. However, replacing columns is not easy, anyway, provided you used rows to model (and vice versa).
In either case, there are pros and cons if the number of dimensions are not known at runtime.
I was looking for self-tested array replacement...
Improved version returns reference or NULL reference and checks boundaries inside.
#include <iostream>
#include <iomanip>
template<typename T, int cols>
class Arr1
{
public:
Arr1(T (&place)[cols]) : me(place) {};
const size_t &Cols = cols;
T &operator [](size_t i)
{
if (i < cols && this != NULL) return me[i];
else {
printf("Out of bounds !\n");
T *crash = NULL;
return *crash;
}
}
private:
T (&me)[cols];
};
template<typename T, int rows, int cols>
class Arr2
{
public:
const size_t &Rows = rows;
const size_t &Cols = cols;
Arr2() {
ret = NULL;
for (size_t i = 0; i < rows; i++) // demo - fill member array
{
for (size_t j = 0; j < cols; j++) matrix[i][j] = cols * i + j;
}
}
~Arr2() {
if (ret) delete ret;
}
Arr1<T, cols>(&operator [](size_t i))
{
if (ret != NULL) delete ret;
if (i < rows) {
ret = new Arr1<T, cols>(matrix[i]);
return *ret;
}
else {
ret = NULL;
printf("Out of bounds !\n");
return *ret;
}
}
//T(&MemberCheck)[rows][cols] = matrix;
private:
T matrix[rows][cols];
Arr1<T, cols> *ret;
};
template<typename T,int rows, int cols>
class Arr
{
public:
const size_t &Rows = rows;
const size_t &Cols = cols;
T(&operator [](size_t i))[cols]
{
if (i < rows) return matrix[i];
else {
printf("Out of bounds !\n");
T(*crash)[cols] = NULL;
return *crash;
}
}
T (&MemberCheck)[rows][cols] = matrix;
private:
T matrix[rows][cols];
};
void main2()
{
std::cout << "Single object version:" << endl;
Arr<int, 3, 4> a;
for (size_t i = 0; i <= a.Rows; i++)
{
int *x = &a[i][0];
if (!x) printf("Fill loop - %i out of bounds...\n", i);
else for (size_t j = 0; j < a.Cols; j++) a[i][j] = a.Cols * i + j;
}
for (size_t i = 0; i < a.Rows; i++)
{
for (size_t j = 0; j <= a.Cols; j++) {
std::cout << std::setw(2) << a[i][j] << ' ';
if (a.MemberCheck[i][j] != a[i][j])
printf("Internal error !");
}
std::cout << std::endl;
}
std::cout << endl << "Double object version:" << endl;
Arr2<int, 3, 4> a2;
for (size_t i = 0; i < a2.Rows; i++)
{
for (size_t j = 0; j <= a2.Cols; j++) {
int &x = a2[i][j];
if (&x)
{
x++;
std::cout << std::setw(2) << a2[i][j] << ' ';
//if (&a2.MemberCheck[i][j] != &a2[i][j])
// printf("Internal error !");
}
}
}
}
Output
Single object version:
Out of bounds !
Fill loop - 3 out of bounds...
0 1 2 3 4
4 5 6 7 8
8 9 10 11 -858993460
Double object version:
1 2 3 4 Out of bounds !
5 6 7 8 Out of bounds !
9 10 11 12 Out of bounds !
it works fine in the program below
#include<iostream>
using namespace std;
class A{
public:
int r,c;
int** val;
A()
{
r=0;c=0;val=NULL;
}
A(int row,int col)
{
r=row;c=col;
int count=0;
val=new int*[row];
for(int i=0;i<r;i++){
val[i]=new int[col];
for(int j=0;j<c;j++){
count++;
val[i][j]=count;
}
}
}
int* &operator[](int index){
return val[index];
}
};
int main(void){
A a(3,3);
cout<<a[1][2];
return 0;
}
here, a[1][2] first computes a[1]-->which returns 2nd row as (int*) type
then it's read as (int*)[2] which returns 3rd element of that row.In short,
a[1][2]------>(a[1])[2]------>(val[1])[2]------>val[1][2].
I have an assignment where i need to use a matrix class of type T elements. I have a constructor using 2 int, one copy constructor, one constructor using a string and a destructor. matrix A uses first constructor and works fine, matrix B uses second and also prints out fine but i have an issue with matrix C. If I a declare it by itself(removing matrix a and b from main) it prints as well, but when all is there, it prints out something like:
3735748 3745176
3745176 3735748
(instead of
5 6
7 8)
And numbers change everytime I compile.
I feel like this should be obvious but i'm a beginner and cant figure it out.. Any help welcome! Thank you
template <class T>
class matrice
{
private :
unsigned int nLignes; //number of rows
unsigned int nColonnes; //nbr of cols
T** rep;
public :
matrice( unsigned int nl, unsigned int nc)
{
setLignes(nl);
setColonnes(nc);
rep = new T*[nl];
for(int i = 0; i < nl; i++){
rep[i] = new T[nc];
}
for(int i = 0; i < nl; i++){
for(int j = 0; j < nc; j++){
rep[i][j] = (T) i*j;
}
}
}
matrice( const matrice& mat)// my copy constructor
{
setLignes(mat.nLignes);
setColonnes(mat.nColonnes);
rep = new T*[nLignes];
for(int i = 0; i < nLignes; i++){
rep[i] = new T[nColonnes];
}
for(int i = 0; i < nLignes; i++){
for(int j = 0; j < nColonnes; j++){
rep[i][j] = (T) i*j;
}
}
}
matrice( const std::string& UnString)//constructor using a string
//"nl,nc,val1, val2.."
{
std::vector<int> vect;
std::stringstream ss(UnString);
int i;
while (ss >> i)
{
vect.push_back(i);
if (ss.peek() == ',')
ss.ignore();
}
setLignes(vect.at(0));
setColonnes(vect.at(1));
int taille = nLignes * nColonnes;
vect.erase(vect.begin(), vect.begin()+2);
if(taille == vect.size()){ // making sure enough values to
//fill array
int n = 0;
for(int i = 0; i < nLignes; i++){
rep[i] = new T[nColonnes];
}
for(int i = 0; i < nLignes; i++){
for(int j = 0; j < nColonnes; j++){
rep[i][j] = vect.at(n);
n++;
}
}
}
}
~matrice()
{
delete[] rep;
}
void afficher();//printing function
void setLignes(int l)
{
nLignes = l;
}
void setColonnes(int c)
{
nColonnes = c;
}
};
template <class T>
void matrice<T>::afficher()//printing function
{
int i,j;
for (i=0;i < nLignes;i++)
{
for(j=0;j < nColonnes;j++)
{
cout << rep[i][j] << " ";
}
cout << "\n";
}
}
/*
*
*MAIN*
******/
int main(int argc, char *argv[])
{
matrice <unsigned int> mat(5,3);//MATRIX A
matrice <unsigned int> a = mat;
a.afficher();
{
matrice <unsigned int> mat(6,6);//MATRIX B
matrice <unsigned int> b = mat;
b.afficher();
}
matrice <unsigned int> c("2,2,5,6,7,8");//MATRIX C !! problem
c.afficher();
system("pause");
return 0;
}
You forget allocate space for rep in the constructor using a string.
Moreover, your deconstructor is at risk of memory leaking, please check it yourself.
I've been working on some code for an assignment and I'm having an issue with nested templated types.
I need the following code to create a 3 element array of 3 element arrays (sort of like int b[3][3]):
Array< Array<int> > b(3);
Here are the relevant parts of my Array.h:
template <class T>
class Array{
public:
Array() : size(0){ data = NULL; }
Array(int s) : size(s) { data = new T[size]; }
Array(const Array & a) : size(a.length()) {
data = new T[a.length()];
for(int i = 0; i < a.length(); ++i)
data[i] = a[i];
}
~Array(){ delete[] data; }
T & operator[](int i) {
if (i >= 0 && i < size){
return data[i];
} else {
throw ArrayOutOfBounds(i);
}
}
T operator[](int i) const{
if (i >= 0 && i < size){
return data[i];
} else {
throw ArrayOutOfBounds(i);
}
}
Array<T> & operator=(const Array<T> &a){
if(this == &a) return *this;
delete[] data;
data = new T[a.length()];
for(int i = 0; i < a.length(); ++i)
data[i] = a[i];
size = a.length();
}
int length() const { return size; }
// Members
private:
int size;
T * data;
}
Update 6/1 the full driver code:
// Test driver for generic Array object with assignment and bounds checking
#include "Array.h"
int main() {
Array<int> a1(10);
for (int i = 0; i < a1.length(); ++i)
a1[i] = i * i;
Array<int> a2 = a1;
try {
for (int i = 0; i <= a2.length(); ++i)
cout << a2[i] << " ";
cout << endl;
}
catch (const ArrayOutOfBounds & e) {
cout << endl << "ArrayOutOfBounds index=" << e.index << endl;
}
Array< Array<int> > b(3);
for (int i = 0; i < b.length(); ++i) {
for (int j = 0; j < b[i].length(); ++j)
b[i][j] = i*b[i].length() + j;
}
for (int i = 0; i < b.length(); ++i) {
cout << "b[" << i << "]= ";
for (int j = 0; j < b[i].length(); ++j)
cout << b[i][j] << " ";
cout << endl;
}
Array<const char *> c(3);
c[0] = "moe"; c[1] = "curly"; c[2] = "larry";
Array<const char *> d(10);
d = c;
for (int i = 0; i < d.length(); ++i)
cout << "d[" << i << "]=" << d[i] << " ";
cout << endl;
return 0;
}
Expected output:
0 1 4 9 16 25 36 49 64 81
ArrayOutOfBounds index=10
b[0]= 0 1 2
b[1]= 3 4 5
b[2]= 6 7 8
d[0]=moe d[1]=curly d[2]=larry
Update 6/2
Per Guillaume's solution, here is the resize method I used:
Array<T> & resize(int newsize){
delete[] data;
data = new T[newsize];
size = newsize;
for(int i = 0; i < size; ++i)
init(data[i], size);
}
Recursive resizing works for higher dimensions, such as Array< Array< Array<int> > > q(3);
Based on the code, you pasted, this should not crash. Did you forget the destructor? You should have a destructor that deletes the memory. When you have one, you need to make sure that data is initialized to nullptr (or NULL) so it does not crash when deleting an empty array.
But your approach is confusing. Is Array size supposed to be determined at runtime or at compile time? int b[3][3] is determined at compile time. If you want that, you should make the size a template argument like std::array in C++11, see http://en.cppreference.com/w/cpp/container/array
If you want to detemrine the size at runtime, you'll need a resize method to determine the size of the the 2nd dimension.
EDIT:
Based on the driver code, you need to do something different in the constructor (passing the int to T if T is an Array). To be quite honest, this seems almost like a bug. This kind of specification makes it really hard to describe what the constructor do (call the default ctor for all types T except for Array)
I'd something like this:
private:
template <typename U>
void init(U&, int) {}
template <typename U>
void init(Array<U>& a, int sz)
{
a.resize(sz);
}
public:
Array(int s) : size(s) {
data = new T[size];
for (int i = 0 ; i < size; ++i) {
init(data[i], s);
}
}
It works but this is ugly. If you can use C++11, you can something nicer with std::enable_if