2

I think the following code snippet is perfectly legal (it builds anyway on MS Visual Studio 2008, C++).

I use it to link to a 3rd party library. But I think because I am passing a pointer to a vector element instead of a regular pointer that the 3rd party library function expects, I get a run-time error

Invalid parameter detected by C-runtime library

What am I doing wrong here?

std::vector<int> vec_ints(27,0);
std::vector<double> vec_doub(27, 0.);
for(int i = 0; i < n; ++i) {
   //-Based on my understanding when i >=27, STL vectors automatically reallocate additional space (twice).
   vec_ints[i] = ...;
   vec_doub[i] = ...;     
}
const int* int_ptr = &vec_ints[0];
const double* doub_ptr = &vec_doub[0];
//-Func is the 3rd party library function that expects a const int* and const double* in the last 2 arguments.
func(...,...,int_ptr,doub_ptr);

But running this after building on MS Visual Studio 2008 (Windows Vista), leads to run-time error as mentioned above, viz.,

Invalid parameter detected by C runtime library

Haven't tested this on Linux yet and I sure would like to avoid copying the contents of the vector into an array just for this. Any ideas what is going on?

Further edit to confirm usage of Nick and Chris' recommendation and to continue discussion with Vlad et al; here's a code snippet:

#include <iostream>
#include <vector>

int main() {
   for(int i=2; i<6; ++i) {
      int isq = i*i;
      std::vector<int> v;
      v.reserve(4);
      for(int j=0; j<isq; ++j) {
         v.push_back(j);
      }
      std::cout << "Vector v: size = " << v.size() << " capacity = " << v.capacity() 
                << "\n";
      std::cout << "Elements: \n";
      for(int k=0; k<v.size(); ++k) {
         std::cout << v.at(k) << "  ";
      }
      std::cout << "\n\n";
   }
   return 0;
}

Gives output:

Vector v: size = 4 capacity = 4
Elements: 
0  1  2  3  

Vector v: size = 9 capacity = 16
Elements: 
0  1  2  3  4  5  6  7  8  

Vector v: size = 16 capacity = 16
Elements: 
0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  

Vector v: size = 25 capacity = 32
Elements: 
0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21  
22  23  24

So atleast for the usage in this context, where no explicit resize is used, it seems to work as intended/expected.

3 Answers 3

3

std::vector<T> expands if you are adding elements using std::vector<T>::push_back(T &), std::vector<T>::insert(iterator, T &) (thanks K-ballo) or explicitly calling std::vector<T>::resize(size_t). Otherwise, it doesn't expand.

std::vector<int> vec_ints;
vec_ints.reserve(27);
std::vector<double> vec_doub;
vec_doub.reserve(27);
for(int i = 0; i < n; ++i) {
    vec_ints.push_back(...);
    vec_doub.push_back(...);    
}
const int* int_ptr = &vec_ints[0];
const double* doub_ptr = &vec_doub[0];
func(...,...,int_ptr,doub_ptr);

You want something like that

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

4 Comments

@Nick! Thanks - you nailed it. I was under the impression that like STL maps, the [] operator could be used to dynamically insert elements. This would've made complete sense infact... wonder why STL decided to do this? It is quite counter-intuitive. I was expecting that when i>27, using [] would simply expand the vector to twice the current size and continue...
@Nick - One side note: What puzzles me is that the error message and my own mistaken notion of how operator [] behaves, led me to misinterpret the error as indicating that I wasn't somehow passing the right arguments to the 3rd party lib.
@user545591 - That's the nature of "undefined behavior." When you write to an address outside the vector, anything at all can happen. It can crash, or not, it can cause unrelated error messages -- anything.
@user545591 The STL designers didn't include the checking and resizing behavior in std::vector<T>::operator [] because they wanted std::vector<T> to replace native arrays without performance penalties.
3

No, vector doesn't expand automatically. You need to expand it yourself:

if (n > 27)
    vec_ints.resize(n, 0);

etc.

9 Comments

I would suggest std::vector::reserve(n). This ensures the vector has enough room for at least n elements.
@Chris: I am afraid, reserve would be still wrong, as it ensures the capacity is at least n and not size. Accessing vector beyond its size is an error.
@Chris, that's not really correct. resize is the correct answer. reserve(m) merely guarantees that future calls to resize(n), if n <= m, will not need to move the data and thereby invalidate iterators. (To expand on @Vlad's correct point, the capacity is always greater than the size. Here we want the size to be at least n)
@Aaron: thanks, I didn't know that reserve ensures validity of iterators after resize.
Thanks Vlad, Chris et al; but I like Chris' suggestion of using reserve(27) at the start. My vector will never have to call resize() function with an argument less than that passed to reserve(), i.e., 27 in this case. In other words my vector can only get bigger than 27; so I should be OK here, I think.
|
1

Why not just create the vectors with the correct size to begin with? Like so:

std::vector<int> vec_ints(n,0);
std::vector<double> vec_doub(n, 0.);

Comments

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.