I would like to check the size() or number of rows in an array of std::vector().
I have vector like
std::vector<int> vec[3];
vec.size() does not work with the above vector declaration.
As for why vec.size() does not work, it's because vec is not a vector, it's an array (of vectors), and arrays in C++ are not objects (in the OOP sense that they are not instances of a class) and therefore have no member functions.
If you want to get the result 3 when doing vec.size() then you either have to use e.g. std::array:
std::array<std::vector<int>, 3> vec;
std::cout << "vec.size() = " << vec.size() << '\n'; // Will output 3
Or if you don't have std::array then use a vector of vectors and set the size by calling the correct constructor:
std::vector<std::vector<int>> vec(3);
std::cout << "vec.size() = " << vec.size() << '\n'; // Will output 3
There's nothing inherent in std::vector<int> vec[3]; to say where the first or second indexing operation constitutes "rows" vs. "columns" - it's all a matter of your own perspective as a programmer. That said, if you consider this to have 3 rows, you can retrieve that number using...
std::extent<decltype(vec)>::value
...for which you'll need to #include <type_traits>. See here.
Anyway, std::array<> is specifically designed to provide a better, more consistent interface - and will already be familiar from std::vector:
std::array<std::vector<int>, 3> vec;
...use vec.size()...
(Consistency is particularly important if you want templated code to handle both vectors and arrays.)
Try
int Nrows = 3;
int Ncols = 4
std::vector<std::vector<int>> vec(Nrows);
for(int k=0;k<Nrows;k++)
vec[k].resize(Ncols);
...
auto Nrows = vec.size();
auto Ncols = (Nrows > 0 ? vec[0].size() : 0);
Either use sizeof(vec[0])/sizeof(vec) or sizeof(vec)/sizeof(vector<int>)
Related
Are these 2 statements std::vector<int> V(N) and std::vector<int> V[N] equivalent??
Also what do they mean?
std::vector<int> V(N) creates an std::vector<int> of size N.
std::vector<int> V[N] creates an array of size N containing std::vector<int>.
You can see this from this piece of code :
#include <vector>
#include <iostream>
#include <typeinfo>
const int N = 100;
int main()
{
std::vector<int> test(N);
std::cout << test.size() << '\n';
std::cout << typeid(test[0]).name() << '\n'; //output i
int i=1; test[0] = i; //runs fine
//std::vector<int> i2; test[0] = i2; //converting error
std::vector<int> test2[N];
std::cout << sizeof(test2)/sizeof(test2[0]) << '\n';
std::cout << typeid(test2[0]).name();
//int i3=1; test2[0] = i3; //converting error
std::vector<int> i4; test2[0] = i4; //runs fine
}
Result:
100
i
100
St6vectorIiSaIiEE
Edit: As #463035818_is_not_a_number and #Eljay mentioned, std::vector<int> V[N] should be written as std::array<std::vector<int>,N> for clarity.
The answer to this question comes in two parts. The first concerns basic syntax, and the second concerns semantics for the std::vector container. One of them is built into the language itself, the other is declared as part of the standard library.
Part 1:
Are these 2 statements std::vector V(N) and std::vector V[N] equivalent??
No. It appears you're confusing built-in array declaration syntax (i.e. the [] brackets), with the "array-like" semantics of the library-declared std::vector<T> object. It might help to recognize that under the hood, std::vector<T> is going to be declared as a struct or class. In a very rough sense, it will look something like this:
template<typename T>
struct vector {
vector();
vector(size_type count);
...
T *storage;
size_type count;
};
Here you see it will have a few different constructors, including one that takes a size_type and pre-allocates memory to store enough elements. A full list of the available constructors for std::vector can be found here.
The () syntax in your example is a call to a constructor, the behavior of which is implementation defined. The square bracket [] declaration syntax is a language feature that tells the compiler to allocate that many objects either on the stack or on the heap, depending on where the allocation occurs.
In most cases (I won't say never because there are always exceptions), you're not going to use std::vector<int> V[N] because std::vector<int> V is already a way to store an "array" of elements.
I'm trying to get to know c++ better and came across this confusion.
int simpleArraySum(const vector<int> ar) {
int n=sizeof(ar)/sizeof(ar[0]);
int sum=0;
for (int i=0; i<n; i++){
sum+=ar[i];
}
return sum;
}
When I passed a vector of 10 elements the result was lower than expected. I checked that n=6 unlike when I use size() which gives n=10. My confusion comes since the way the code is written works normally in main with sizeof(ar)/sizeof(ar[0]).
Using the "sizeof trick" have never worked on a std::vector.
The size of a std::vector object is the size of the std::vector object itself, not the possible data handled by the vector.
If you want to get the number of elements from a std::vector object, use the size member function.
The "sizeof trick" only works on actual arrays, like e.g.
int array[10];
std::cout << sizeof(array) / sizeof(array[0]) << '\n'; // Will print 10
As for the problem you try to solve with your function, there are much better ways to handle it.
First you could iterate using the size (like you do now)
for (size_t i = 0; i < ar.size(); ++i)
sum += ar[i];
Then you could iterate using iterators
for (auto i = ar.begin(); i != ar.end(); ++i)
sum += *i;
Then you have range-based for loops
for (auto value : ar)
sum += value;
Lastly you can use a standard algorithm function like std::accumulate
int simpleArraySum(std::vector<int> const& ar)
{
return std::accumulate(begin(ar), end(ar), 0);
}
Why does sizeof(ar)/ sizeof(ar[0]) not work properly on a vector ...
sizeof(ar)/ sizeof(ar[0]) is an expression that gives you the length of an array, and only an array. std::vector is not an array. std::vector is a class (template).sizeof(std::vector) is entirely unrelated to the number of elements it has i.e. its length.
The size of all types is compile time constant. std::vector's can contain a variable number of elements that is not compile time constant. Therefore the size of vector type cannot depend on the number of elements.
... when passed to a function?
It won't work when not passing into a function either.
I have the following array:
int* myArray = new int[45];
If I wanted to iterate each element without knowing the actual size of the array, I would need to use a for_each?
If so, then how would you write the for_each? I was looking over the following site and reading up on for_each but can't figure out how to put this together.
http://www.cplusplus.com/reference/algorithm/for_each/
Update: A for_each is not a good choice in this case, due to the fact that the size of the array has to be known. vectors are the proper way to accomplish such task. My reason for using arrays, in this case, was for learning purposes. if this was a serious project I would move to something such as Lists/Vectors.
Note when the question was first posted, the array in question was declared as
int myArray[45];
This answer deals with that particular case.
If you have C++11 support, you can use a range based loop:
for (int& i : myArray) {
std::cout << i << "\n";
}
C++11 also provides std::begin and std::end, which you can use with a fixed size array to obtain iterators:
std::for_each(std::begin(myArray), std::end(myArray), <func>);
Another option, which works for C++03 and you are dealing with fixed size arrays, is to define a function template:
// taken a fixed size array by reference and loop over it
template <typename T, unsigned int N>
void array_for_each( T (&a)[N]) {
for (unsigned int i = 0; i < N; ++i) {
// do something with array elements
std::cout << a[i] << " ";
}
}
int main() {
int a[5];
array_for_each(a);
}
If you use MSVC (Microsoft Visual C++), you can use "for each."
for each(int i in arr) {
cout << i << ' ' << endl;
}
NOTE: This only works in the block of code the array is declared in.
If not, you can also use the new range-based for loop in the C++11 standard.
for(int i : arr) {
cout << i << ' ' << endl;
}
If you're intent upon the std::for_each:
for_each(arr,arr + 10,[] (int i) {
cout << i << ' ' << endl;
});
NOTE: This requires knowledge of the size of the array (in this example, 10).
You could use a for_each. In this case, you have allocated space for 45 elements in your array, but since it is NULL, you'd probably get a segfault if you tried to do anything. You either need to hold a value of the array, or use something like sizeof(myArray)/sizeof(myArray[0]) (which has its own problems).
Anyway, for a for_each here, if we actually had 45 elements:
std::for_each(myArray, myArray + 45, <func>);
Anyway, this is part of the reason to use vectors: .begin() and .end() reduces errors with using incorrect indexing.
You have described an array of int, not a class that implements a InputIterator, which is what the for_each is designed for, even though you can use it to iterate an array, but you need to know the size of the array to iterate it.
If you want to use for_each you need to use a vector, list, or implement a class that keeps track of the number of elements it contains. IMO it is much easier to just use a vector
If you want to just iterate your current array, assuming it is 0 terminated:
for(int *value = myArray; *value != 0; ++value)
printf("%d\n", *value);
Or, you can use indexes:
for(int index = 0; myArray[index] != 0; ++index)
printf("%d\n", myArray[index]);
IMO the pointer method is cleaner.
This code is still dangerous though, you should either keep track of the number of records in a seperate variable, or use a vector.
It is possible to initialise a vector from an array holding elements with the same type as vector, such as
double a[] ={ somevalues };
std::vector<double> vec(a, a+dimension)
I was wondering whether the other way around is possible or not without an explicit loop? Is that possible to initialise an array from a vector with a short cut like the one above, I guess not but let me ask ...
No, it is not possible to do it at initialization, but you can use one algorithm from the STL:
std::vector<int> v = create_vector();
int array[100];
assert( v.size() >= 100 );
std::copy( v.begin(), v.begin()+100, array );
Or alternatively:
std::copy_n( v.begin(), 100, array );
The assert is to ensure that you don't go beyond the size of the vector (which would cause undefined behavior), and limiting the copies (the 100 in the expressions) so that you don't overflow the array either.
Yes you can initialize a vector from an array of the same type:
int a[] = {16,2,77,29};
vector<int> v (a, a + sizeof(a) / sizeof(*a) );
You can use std::copy to copy the vector to an array
copy( v.begin(), v.begin()+MAX_SIZE, a); // or v.end() if a is large enough to hold the whole vector
Alternative to what was answered in this question is to have a pointer associated with vector's first variable (vector lays in contiguous memory):
assume following vector:
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
our pointer:
int *num_arr = &v[0];
Advantages - instead of doubling the amount of memory by creating a new dynamic array of vec.capacity() size, you have a pointer to vec's first element, with which you can do the same thing as normal array, except that you have to pass the size, but anyway you can't estimate the size of dynamically allocated array through sizeof(array) / sizeof(*array).
calling the function:
print_out_array(&v[0], v.size());
you can have a function that prints out the "array":
print_out_array(const int* array, std::size_t size){
cout << "Printing out array:" << endl;
for (int i=0; i != size; ++i){
cout << "i: " << i << ", value: " << array[i] << endl;
}
}
See, in that function array[i] works just like array, no copies involved, no overhead in copying, no new memory is allocated - all good! :)
But you have to be careful if the vector is empty though. If v.size() is zero then &v[0] attempts to produce a pointer to something that doesn't exist - undefined behaviour.
Safer way:
if(!v.empty()){
print_array(&v[0],v.size());
}
But be careful with strings though... they are completely different beasts...
To get full information about that matter have a look in Scott Meyer's Effective STL Item 16. Know how to pass vector and string data to legacy APIs.
No. You can use
double a[] = { v[0], v[1], ... };
but easier you cannot get.
How do I reliably get the size of a C-style array? The method often recommended seems to be to use sizeof, but it doesn't work in the foo function, where x is passed in:
#include <iostream>
void foo(int x[]) {
std::cerr << (sizeof(x) / sizeof(int)); // 2
}
int main(){
int x[] = {1,2,3,4,5};
std::cerr << (sizeof(x) / sizeof(int)); // 5
foo(x);
return 0;
}
Answers to this question recommend sizeof but they don't say that it (apparently?) doesn't work if you pass the array around. So, do I have to use a sentinel instead? (I don't think the users of my foo function can always be trusted to put a sentinel at the end. Of course, I could use std::vector, but then I don't get the nice shorthand syntax {1,2,3,4,5}.)
In C array parameters in C are really just pointers so sizeof() won't work. You either need to pass in the size as another parameter or use a sentinel - whichever is most appropriate for your design.
Some other options:
Some other info:
for C++, instead of passing a raw array pointer, you might want to have the parameter use something that wraps the array in a class template that keeps track of the array size and provides methods to copy data into the array in a safe manner. Something like STLSoft's array_proxy template or Boost's boost::array might help. I've used an array_proxy template to nice effect before. Inside the function using the parameter, you get std::vector like operations, but the caller of the function can be using a simple C array. There's no copying of the array - the array_proxy template takes care of packaging the array pointer and the array's size nearly automatically.
a macro to use in C for determining the number of elements in an array (for when sizeof() might help - ie., you're not dealing with a simple pointer): Is there a standard function in C that would return the length of an array?
A common idiom mentioned in GNU Libstdc++ documentation is the lengthof function:
template<typename T, unsigned int sz>
inline unsigned int lengthof(T (&)[sz]) { return sz; }
You can use it as
int x[] = {1,2,3,4,5};
std::cerr << lengthof(x) << std::endl;
Warning: this will work only when the array has not decayed into a pointer.
How about this?..
template <int N>
void foo(int (&x)[N]) {
std::cerr << N;
}
You can either pass the size around, use a sentinel or even better use std::vector. Even though std::vector lacks initializer lists it is still easy to construct a vector with a set of elements (although not quite as nice)
static const int arr[] = {1,2,3,4,5};
vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) );
The std::vector class also makes making mistakes far harder, which is worth its weight in gold. Another bonus is that all C++ should be familiar with it and most C++ applications should be using a std::vector rather than a raw C array.
As a quick note, C++0x adds Initializer lists
std::vector<int> v = {1, 2, 3, 4};
You can also use Boost.Assign to do the same thing although the syntax is a bit more convoluted.
std::vector<int> v = boost::assign::list_of(1)(2)(3)(4);
or
std::vector<int> v;
v += 1, 2, 3, 4;
c provides no native support for this. Once an array is passed out of its declared scope, its size is lost.
You can pass the size with the array. You can even bundle them into a structure if you always to to keep the size, though you'll have some bookkeepping overhead with that.
I also agree that Corwin's method above is very good.
template <int N>
void foo(int (&x)[N])
{
std::cerr << N;
}
I don't think anybody gave a really good reason why this is not a good idea.
In java, for example, we can write things like:
int numbers [] = {1, 2, 3, 4};
for(int i = 0; i < numbers.length(); i++)
{
System.out.println(numbers[i]+"\n");
}
In C++ it would be nice instead of saying
int numbers [] = {1, 2, 3, 4};
int size = sizeof(numbers)/sizeof(int);
for(int i = 0; i < size; i++)
{
cout << numbers[i] << endl;
}
We could take it a step further and go
template <int N>
int size(int (&X)[N])
{
return N;
}
Or if that causes problems I suppose you could write explicitly:
template < int N >
int size(int (&X)[N])
{
int value = (sizeof(X)/sizeof(X[0]));
return value;
}
Then we just have to go in main:
int numbers [] = {1, 2, 3, 4};
for(int i = 0; i < size(numbers); i++)
{
cout << numbers[i] << endl;
}
makes sense to me :-)
An array expression will have its type implicitly converted from "N-element array of T" to "pointer to T" and its value will be the address of the first element in the array, unless the array expression is the operand of either the sizeof or address-of (&) operators, or if the array expression is a string literal being used to initialize another array in a declaration. In short, you can't pass an array to a function as an array; what the function receives is a pointer value, not an array value.
You have to pass the array size as a separate parameter.
Since you're using C++, use vectors (or some other suitable STL container) instead of C-style arrays. Yes, you lose the handy shorthand syntax, but the tradeoff is more than worth it. Seriously.
Now, you can use C++11's extent and rank.
By example:
#include <iostream>
#include <type_traits>
int main()
{
int a[][3] = {{1, 2, 3}, {4, 5, 6}};
std::cout << "\nRank: : " << std::rank<decltype(a)>::value;
std::cout << "\nSize: [_here_][]: " << std::extent<decltype(a), 0>::value;
std::cout << "\nSize: [][_here_]: " << std::extent<decltype(a), 1>::value;
std::cout << "\nSize: [][]_here_: " << std::extent<decltype(a), 2>::value;
}
prints:
Rank: : 2
Size: [_here_][]: 2
Size: [][_here_]: 3
Size: [][]_here_: 0
You need to pass the size along with the array, just like it is done in many library functions, for instance strncpy(), strncmp() etc. Sorry, this is just the way it works in C:-).
Alternatively you could roll out your own structure like:
struct array {
int* data;
int size;
};
and pass it around your code.
Of course you can still use std::list or std::vector if you want to be more C++ -ish.
Since c++11, there is a very convenient way:
static const int array[] = { 1, 2, 3, 6 };
int size = (int)std::distance(std::begin(array), std::end(array))+1;