Reputation: 161
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
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
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