tags:

views:

72

answers:

3

Hi everyone,

I'm writing a class that holds a matrix (of double values), represented as vector<vector<double>>;

I want to implement the operator=, to re-fill my matrix with the details of a given sparse matrix. I'm writing the following code:

RegMatrix& RegMatrix::operator=(const SparseMatrix rhs){
    if(*this != rhs){
        _matrix.clear();
        _matrix.resize(rhs.getRow());
        int i;
        for(i=0;i<rhs.getRow();++i){
            _matrix.at(i).resize(rhs.getCol());
        }

        for(i=0;i<rhs.getSize();++i){
            Element e = rhs.getElement(i);
            _matrix[e._row][e._col] = e._val; 
        }
    }

    return *this;
}

Does the resize() method fill automatically the vector with zeros? Is my implementation ok?

+5  A: 

New elements take the vector member's default value, or a specific value if you use the overload of resize with two parameters.

void resize(
   size_type _Newsize,
   Type _Val
);

In your case, the default will be an empty vector<double> - if that is not what you want, pass what you DO want to put there to the overload above.

Existing elements are not modified.

Steve Townsend
so, if i want a two-dimensional vector of the zise RowXCol, and each inner vector's element will have the value of 0, i should change the line so it would look like that: _matrix.at(i).resize(rhs.getCol(),0); ?
limlim
@limlim: You don't need to change it. You are already passing that zero *implicitly*. You can also pass that zero explicitly, but it will not change anything. If you believe that passing that 0 explicitly makes your code clearer, then you can go ahead and put it there. But it will make no difference functionality-wise.
AndreyT
If I'm not mistaken, resize won't zero the existing elements. If that's what you want to do, use assign (check out my answer for more).
JoshD
@JoshD: The OP's vectors do not have any "existing elements". They are always *empty* before `resize` call.
AndreyT
@AndreyT, then why does he bother to call clear()? That's a wasteful step. Because this is an assignment operator, it is reasonable to assume that there may be some contents in the _matrix. A call to assign covers both cases and is preferred to calling clear then resize.
JoshD
@AndreyT: What part of "re-fill" do you not understand? (And no need to be so loud.)
c-urchin
@JoshD: Er... He doesn't have any exiting elements *because* he called `clear` in advance. That's what I'm talking about. Why you call it a "wasteful step" is not entirely clear to me. The solution you suggested yourself (with `assign`) is just a wrapper over `clear` (at least by specification) followed by a sequence of even less efficient steps.
AndreyT
@c-urchin: Huh? What are you talking about?
AndreyT
A: 

None of std::vector<> methods ever use any form of default initialization internally. std::vector<> only requires its elements to be CopyConstructible and Assignable, but does not require them to be DefaultConstructible. Every time you run into a situation when some elements seem to be constructed "out of nothing" (as is the case with your resize calls) it normally means that the std::vector<> method you are using has an extra parameter, which allows you to pass the value from which the new elements will be copy-constructed. We don't often notice that, since these arguments are always supplied with default values equal to the ()-initailized element of the corresponding type.

In your case, the

_matrix.at(i).resize(rhs.getCol());

is actually translated into

_matrix.at(i).resize(rhs.getCol(), double());

call, meaning that formally it is you who's implicitly passing the initial value for the new elements.

double() evaluates to zero, so yes, the column vectors will be filled with zeros initially.

AndreyT
No, only the newly-added elements (if any) will be zero.
c-urchin
@c-urchin: Huh? Firstly, when I say "new elements" a mean newly-added elements, which is sufficiently clear. Secondly, my last remark applies to the specific OP's code, where the vector is *empty* initially. So, it will be *filled* with zeros after resize, as I said.
AndreyT
@AndreyT: Why so touchy? In point of fact, the OP says (please reread it) "re-fill" which implies that some values have already been set.
c-urchin
@c-urchin: Please, pay attention. The OP's explicitly calls `clear` before doing any other actions. So, there are *no existing elements* at the moment of `resize`. What part of that don't you understand?
AndreyT
A: 

If you want to zero out the entire 2d array, you can use the assign function of vector:

v.assign(size, vector<double>(size, 0.));

This will make a 2d vector of sizeXsize filled with zeros.

In your case:

RegMatrix& RegMatrix::operator=(const SparseMatrix rhs){
    if(*this != rhs){
        _matrix.assign(rhs.getRow(), vector<double>(rhs.getCol(), 0.));

        for(i=0;i<rhs.getSize();++i){
            Element e = rhs.getElement(i);
            _matrix[e._row][e._col] = e._val; 
        }
    }

    return *this;
}
JoshD
No formal need for an explicit `0` as well. `v.assign(size, vector<double>(size))` will do the same thing.
AndreyT