0

For some reason, resizing this two dimensional vector in my class does not work. Thanks for your help!

..
Map::Map(const unsigned int& w,
         const unsigned int& h,
         const unsigned int& s)
    : width(w), height(h), size(s)
{
    squares.resize(width);
    for (unsigned int i = 0; i < width; ++i)
    {
        squares[i].resize(height); // error here
        for (unsigned int j = 0; j < height; ++j)
        {
            squares[i][j] = Square(sf::Vector2f(i * size, j * size));
        }
    }
}

std::vector<std::vector<Square>> squares;
..

Some error messages:

c:\mingw\bin..\lib\gcc\mingw32\4.6.2\include\c++\bits\stl_uninitialized.h|481| instanziiert von »static void std::__uninitialized_default_n_1<TrivialValueType>::_uninit_default_n(_ForwardIterator, _Size) [with _ForwardIterator = Square*, _Size = unsigned int, bool _TrivialValueType = false]«|

c:\mingw\bin..\lib\gcc\mingw32\4.6.2\include\c++\bits\stl_uninitialized.h|529| instanziiert von »void std::__uninitialized_default_n(_ForwardIterator, _Size) [with _ForwardIterator = Square*, _Size = unsigned int]«|

7
  • Does Square have a default constructor? Commented Jul 5, 2013 at 18:02
  • 1
    consider using boost::multi_array instead of nested vectors Commented Jul 5, 2013 at 18:03
  • Yes, it has a default constructor: Square(const sf::Vector2f& pos); Commented Jul 5, 2013 at 18:05
  • default constructor is a constructor that takes no arguments. what you posted is a constructor that needs one argument and therefore should be marked explicit to avoid implicit conversions Commented Jul 5, 2013 at 18:07
  • @aryjczyk multi_array is, by name, an array, not a vector Commented Jul 5, 2013 at 18:07

1 Answer 1

1

When you vector.resize(n) and n > vector.size() you are asking it to create n - vector.size() new elements. Vector needs to default construct them, since he doesn't know what arguments to use. If they are not default constructible, resize fails.

However, if you don't want Square to be default constructible you can change failing line to vector.reserve() - that only makes sure there is enough space for new elements, but doesn't actually create them. Then you can create them one by one in a loop using

squares[i].emplace_back(sf::Vector2f(i * size, j * size));

Oh, and by the way passing primitives by reference has suboptimal performance. Pass them by value unless you need them as out parameters.

Sign up to request clarification or add additional context in comments.

3 Comments

So is it a good practice to only use const references in method parameters when it's not a primitive type?
in general if you are not passing an out argument it should be either passed by value or by const reference. there are 2 differences 1) performance - passing by value copies the object, passing by ref is under the hood passing by pointer, so there is a level of indirection, so you want to pass small things by value and big ones by reference. i've read somewhere, that 16B is a good threshold on x86, but it's more of a guideline than a rule. if you find yourself writing code that passes a lot of small structs in perf-critical areas you should profile it and see what's best
2) if you want to perform some intermediate non-const computation on an argument, you would need to copy it anyway, so it's okay to pass it by value even if it's big

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.