RoestVrijStaal
RoestVrijStaal

Reputation: 161

Initialize std::vector in class's initializer list

I'm not sure if I should ask this at StackOverflow or at CodeReview. But because I couldn't find a similair problem, I'm posting it here.

ATM I'm optimizing the code of a simple image manipulation application.

One of the targets is to give all the convolution effect classes their respective matrix as their private variable. Because const-correctness this wasn't done earlier, but the quickfix to solve the introduced problems with const-correctness wasn't sparely with memory and cpu-cycles.

So I decided to init the convolutionMatrix at class-initializiation-level with a std::vector<std::vector<double>> since creating dozens of constructors to make each initialisation with std::array<std::array<double>,\d+>,\d+> possible, is inefficient.

BlurFilter::BlurFilter() : ColorEffect(), convolutionMatrix(
std::vector<std::vector<double>>{
    std::vector<double>{ 0.0, 0.0, 1.0, 0.0, 0.0 },
    std::vector<double>{ 0.0, 1.0, 1.0, 1.0, 0.0 },
    std::vector<double>{ 1.0, 1.0, 1.0, 1.0, 1.0 },
    std::vector<double>{ 0.0, 1.0, 1.0, 1.0, 0.0 },
    std::vector<double>{ 0.0, 0.0, 1.0, 0.0, 0.0 }
} )
{
}

However. the application breaks at runtime in the Matrix constructor with an std::out_of_range-exception with the what()-message:

what(): vector::_M_range_check: __n (which is 0) >= this->size() (which is 0)"

Aka multidimensionalVector.size() is somehow 0.

Matrix::Matrix( const std::vector<std::vector<double>>& multidimensionalVector )
{
    this->xLength = multidimensionalVector.size();
    this->yLength = ( *multidimensionalVector.begin() ).size();
    this->values = multidimensionalVector;
}

Honestly I don't understand why the size of the multidimentsionalVector is zero at that moment at all since I'm passing an initialized vector of vectors which could be -as shown- copy-constructed (or move-constructed) over to the values-variable of the Matrix class. Changing multidimensionalVector copy-by-value don't make the difference.

Could someone explain where and/or what is going wrong here?

(PS: I'd prefer answers written in own words (aka in Plain English) instead of citing directly from the C++ standard documents because of the used vague and confusing academic/scientific language).

Upvotes: 1

Views: 3007

Answers (2)

RoestVrijStaal
RoestVrijStaal

Reputation: 161

Well, This is embarrassing of me.

It seems I've fixed my own problem unintentionally when I was stripping and optimizing my code for posting this question. I didn't thought about to try out the streamlined code before posting it.

Putting

this->values = multidimensionalVector;

did the job.

The original of the Matrix-constructor which seemed to raise the std::out_of_range-exception was this:

Matrix::Matrix( const std::vector<std::vector<double>>& multidimensionalVector )
{
    this->xLength = multidimensionalVector.size();
    this->yLength = ( *multidimensionalVector.begin() ).size();

    for( int x = 0; x < this->xLength; x++ )
    {
        for( int y = 0; y < this->yLength; y++ )
        {
            this->set( x, y, multidimensionalVector.at( x ).at( y ) );
        }
    }
}

Within Matrix::set(int x, int y, double newValue ), the x and y parameters are always checked if they're in between -1 and this->xLength && between -1 and this->yLength.

But the x and y parameters are never checked if they're in bounds with the (then not initialized) this->values...

Upvotes: 1

R Sahu
R Sahu

Reputation: 206567

FWIW, you can simplify your code quite a bit. Here's an example that works:

#include <iostream>
#include <vector>

struct Matrix
{
   Matrix(const std::vector<std::vector<double>>& multidimensionalVector);
   size_t xLength;
   size_t yLength;
   std::vector<std::vector<double>> values;
};

Matrix::Matrix( const std::vector<std::vector<double>>& multidimensionalVector ) : xLength(0), yLength(0), values(multidimensionalVector)
{
    this->xLength = values.size();
    std::cout << "xLength: " << xLength << std::endl;
    if ( xLength > 0 )
    {
       this->yLength = ( *values.begin() ).size();;
    }
    std::cout << "yLength: " << yLength << std::endl;
}

struct BlurFilter
{

   BlurFilter();

   Matrix convolutionMatrix;
};

BlurFilter::BlurFilter() : convolutionMatrix( { { 0.0, 0.0, 1.0, 0.0, 0.0 },
                                                { 0.0, 1.0, 1.0, 1.0, 0.0 },
                                                { 1.0, 1.0, 1.0, 1.0, 1.0 },
                                                { 0.0, 1.0, 1.0, 1.0, 0.0 },
                                                { 0.0, 0.0, 1.0, 0.0, 0.0 } } )
{
}

int main()
{
   BlurFilter f;
}

Upvotes: 2

Related Questions