2

So I started learning C++ last week and naturally, I want to become familiar with the whole pointer and object-oriented business and so on and so forth.

To do that, I'm writing a very simple program for some basic matrix calculations:

# include <iostream>
using std::cout;
using std::cin;

class Matrix {
        int columns; // x
        int rows; // y
        double* matrix;
    public:
        Matrix (int*);
        void printMatrix();
        void free() {
            delete[] matrix;
            return;
            };
};

Matrix::Matrix(int* dim){
    rows = *dim;
    columns = *(dim + 1);
    matrix = new double [columns*rows];
}

void Matrix::printMatrix(){ 
    int i, j;
    for(i = 0; i < columns; i++){
        for(j=0; j < rows; j++){
            cout << matrix[columns*i + j] << " ";
        }
        cout << "\n";
    }
    return;         
}


int* getMatrix ();

int main () {
    Matrix matrix (getMatrix());
    matrix.printMatrix();
    matrix.free();
    return 0;
}

int* getMatrix (){
    int* dim = new int [2];
    cout << "(m x n)-Matrix, m? ";
    cin >> dim[0];
    cout << "n? ";
    cin >> dim[1];
    return dim;
}

The problem (as I see it) occurs when I choose a (4,2) matrix. As I understand from various tutorials,

matrix = new double [columns*rows];

should allocate this much memory: columns*rows times sizeof(double). Also, every 'cell' should be initialized with a 0.

But, choosing a (4,2) matrix, I get the following output, of the function printMatrix():

0 0 
0 0 
0 6.6727e-319 
0 0 

Why is the (3,2) entry not initialized with 0?

Thanks!

Jo Mo
  • 155
  • 7

2 Answers2

3

Also, every 'cell' should be initialized with a 0.

Nope. The language does not do that for you, when you write new double[N].

Why is the (3,2) entry not initialized with 0?

It will if, you write new double[N]() instead!

[C++11: 5.3.4/15]: A new-expression that creates an object of type T initializes that object as follows:

  • If the new-initializer is omitted, the object is default-initialized (8.5); if no initialization is performed, the object has indeterminate value.
  • Otherwise, the new-initializer is interpreted according to the initialization rules of 8.5 for direct-initialization.

Granted, this is slightly ambiguous in that it would seem to be talking about the non-array versions of new, but in fact it means both; T is double[4].

In fact, we can see that the same section of wording talks about "object" in both the array and non-array cases, setting the perfect precedent:

[C++11: 5.3.4/1]: [..] If the entity is a non-array object, the new-expression returns a pointer to the object created. If it is an array, the new-expression returns a pointer to the initial element of the array.

Now, it's essentially impossible to prove this rule, because you can strike unlucky and get all-zeroes even when those values are in fact indeterminate, but the following code entirely unconvincingly makes a good start:

#include <iostream>
#include <vector>

int main() {
    const std::size_t n = 4;

    {
        std::vector<double> hack;
        hack.push_back(5);
        hack.push_back(6);
        hack.push_back(7);
        hack.push_back(8);
        hack.push_back(9);
        hack.push_back(10);
        hack.push_back(11);
        hack.push_back(12);
    }

    double* a = new double [n];
    double* b = new double [n]();

    for (std::size_t i = 0; i < n; i++)
        std::cout << a[i] << '/' << b[i] << ' ';
    std::cout << '\n';

    delete[] a;
    delete[] b;
}

I managed to get 0/0 6/0 7/0 8/0 from it, thanks to some heap hackery, but it's still only just pure chance and doesn't really demonstrate anything (live demo).

Unfortunately, new double[4](316) isn't valid (providing a value inside the () is explicitly banned for arrays during direct-initialization, per [C++11: 8.5/16] ) so we can't suggest that new double[4](0) would be reliable and use the example with 316 to convince you of it.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
2

Only static variables are initialized to 0 in C++.
Auto and dynamic variables should be initialized by you.

cppcoder
  • 22,227
  • 6
  • 56
  • 81