we can initialize a vector using array. suppose,
int a[]={1,2,3}
vector<int>x(a,a+3)
this is a way . My question is, what is a and a+3 here, are they pointer?
and someone could explain this:
for the above array
vector<int>x(a,&a[3])
also gives no error and do the same as above code. If we write a[3], it should be outside of the array? can someone tell me the inner mechanism?
Yes, a and a+3 are pointers. The plain a is an array that gets converted implicitly to a pointer at the drop of a hat.
The construct &a[3] is identical in meaning to a+3 for plain C arrays. Yes, a[3] is outside the array, but one-past is allowed to point to, if you don't dereference it.
A vector's range constructor looks like this:
template <class InputIterator>
vector (InputIterator first, InputIterator last,
const allocator_type& alloc = allocator_type());
It will construct elements in the range [first, last), meaning that the last element is not included. &a[3] points to an element outside the bounds of the array, similar to how std::end(a) will point one past the end of a. Compare it to:
std::vector<int> x(std::begin(a), std::end(a));
Also, *(a + 3) is equivalent to a[3].
int a[]={1,2,3}
vectorx(a,a+3)
a is an array so it is always pointing to its base address.
a+3 mean base address+(sizeof(int) *3)
suppose base address is 100
a=100;
a+3=106;
vectorx(a,&a[3])
Here &a[3] is equivalent to a+3
Related
sort (arr, arr + n)
Why do we write arr + n in sort function in (function in algorithm library) C++. What does it mean arr + n?
std::sort accepts iterators to beginning and end of some range (end points to first element beyond range).
A pointer can be an iterator
In C an array of type sometype[n] decays to a pointer of type: sometype*. So arr is treated as a pointer and arr + n advances this pointer by n elements (so it point to first element beyond array).
Now alternative ways to write this code to make it more clear and less bug prone:
std::sort(std::begin(arr), std::end(arr));
// or using C++20 ranges:
std::ranges::sort(arr);
Given the declaration of type arr[], the expression arr + n is evaluated as the address of the nth element in arr.
In other words (hoping that it helps clarifying), arr + n is equivalent to &arr[n].
std::sort takes a pair of iterators and them uses std::swap to sort the elements in that range.
The iterators must provide implementations for operator* and operator++. These requirements are defined as "named requirements" here.
If you thing about it, any pointer fulfills these criteria.
In other words, you can think of iterators as a generalization of pointers. By passing a pointer to the first &arr[0] and a pointer to one past the last element &arr[n] you are providing the begin and end iterators. arr and arr + n are fancy abbreviations for &arr[0] and &arr[n].
Can I convert std::vector element pointer to index with this?
http://coliru.stacked-crooked.com/a/cedf3d849539e001
template<class T>
std::size_t get_index(std::vector<T>& vec, T* ptr){
const std::size_t i = ptr - &(*vec.begin());
return i;
}
If elements in vector is guaranteed to be contiguous, then I think we can do such pointer arithmetic... Or no?
Vector elements are stored contiguously, yes. You can also use std::vector<T>::data() instead of &*std::vector<T>::begin().
You can read more at: http://en.cppreference.com/w/cpp/container/vector
PS: There is already a question about this - Are std::vector elements guaranteed to be contiguous?
If elements in vector is guaranteed to be contiguous, then I think we can do such pointer arithmetic...
Elements in vector are guaranteed to be contiguous, and you can use such pointer arithmetic indeed.
However, there is a caveat: addressof operator can be overloaded to return something other than the address. If you cannot guarantee that it won't be overloaded, use std::addressof instead.
Or simply use std::vector::data as shown by Ivan.
I've made a container class in C++, and I have a constructor from iterators so I can write MyContainer<double> x(v.begin(), v.end()) where v is a std::vector<double>. I would like to be able to do the same with a c-array but :
double array[3] = {1., 2. , 3.};
MyContainer<double> x(array, array+3); // Doesn't work : no matching function for call to ‘MyContainer<double>::MyContainer(double [3], double*)’
MyContainer<double> x(array+0, array+3); // Work
What is the origin of the problem and how to solve it ?
Thank you very much.
Don't accept references to iterators, take them by value. It's trying to pass a reference to an array; the failing expression needs the array to decay to a pointer.
Presumably you have
template< typename Iter >
MyContainer( Iter const &first, Iter const &last );
but you need
template< typename Iter >
MyContainer( Iter first, Iter last );
Iterators need to be lightweight enough to pass by value; all the standard templates do so.
An array cannot be used as an iterator because it cannot be incremented. The storage is fixed. When you use an array in an expression like arr + 0 or pass it by value to a function, it is implicitly converted to a pointer to its first element. But that conversion doesn't happen when passing by reference.
The result of array+0 is a pointer, while array itself is not a pointer, it is an array. Your constructor does not have an overload that takes an array and a pointer, hence the compile fails.
The idiomatic way of dealing with the problem of making the beginning and the ending iterators from an array is using the begin(...) and end(...) functions:
MyContainer<double> x(std::begin(array), std::end(array));
The overload takes care of figuring out where the end of your array is, freeing you from the need to add array's length to the pointer.
int arr[5] = {0,1,2,3,4};
vector<int> vec;
normally we do:
vector<int> vec(arr, arr + sizeof(arr) / sizeof(int));
but how do initialize a vector vec with only first 3 values of arr?
Also how do I initialize it with the middle 3 values?
I have to initialize it right away, no push_back on multiple lines..
The constructor form you are invoking is this**:
template <class Iterator> vector(Iterator start, Iterator end);
So, you may pass in anything that acts like a pair of iterators. Specifically, you may pass in two pointers, as long as they both point into the same array, and as long as the 2nd doesn't come before the first (if the pointers are equal, they represent an empty range).
In your example, you pass in a pointer to the first element of the array and a pointer to the (mythical) elment-after-the-last-element of the array:
vector<int> vec(arr, arr + sizeof(arr) / sizeof(int));
Generally, you may pass in a pointer to any element as the start, and a pointer past any element as the finish.
but how do I initialize a vector vec with only first 3 values of arr?
Pass in pointers to the first and one past the third elements:
vector<int> vec(arr, arr+3);
Also how do I initialize it with middle 3 values?
Pass in a pointer to the first item you want to copy, and a pointer to one paste the final element. In this case, indexes 1 and 4:
vector<int> vec(arr+1, arr+4);
** Okay, it is slightly more complicated than that, but it's okay to pretend for the sake of this discussion. The actual form is: template <class InputIterator>
vector( InputIterator first, InputIterator last,
const Allocator& alloc = Allocator() );
Can someone explain this code please? how is it that the function bar accepts a reference to the first element of the vector?
jintArray arry;
std::vector<int> foo = GetIntegerArray(env, arry);
bar(&foo[0])
where the protoytpe of bar is
bar(int* array)
This is valid as long as the template type isn't bool. The C++ vector type specifies that the vector elements are consecutive in memory like that so that you can do exactly this.
The reason why it doesn't work with bool is due to template specialization. Where the bools are compressed down to a bitfield.
http://en.wikipedia.org/wiki/Vector_%28C%2B%2B%29#vector.3Cbool.3E_specialization
how is it that the function bar accepts a reference to the first element of the vector?
This seems to be the source of the confusion. The expression &foo[0] is not a reference to the first element, but rather a pointer. operator[] is overloaded in the vector class to obtain a reference (or const-reference), and applying & will obtain the address of the object.
Yes. Just make sure the vector is not empty, or &foo[0] would be an error. C++11 introduced the std::vector<T>::data() function that does not have this problem.
Also, returning a vector by value is usually not a good idea. You might want to use an output iterator or a vector reference parameter in GetIntegerArray, so you would call it like this:
std::vector<int> foo;
GetIntegerArray(env, arry, back_inserter(foo));
or
std::vector<int> foo;
GetIntegerArray(env, arry, foo);
When you use std::vector<int>, it is guaranteed that all the element are created in contiguous memory. As such, when you write &v[0] it returns the pointer to the first element, and from this you can go the next element by writing &v[0]+1, and so on.
By the way, if you want to traverse through all elements or a section of elements, then a better interface for bar would be this:
void bar(int *begin, int *end)
{
for ( ; begin != end; ++begin)
{
//code
}
}
So you can call like this:
bar(&foo[0], &foo[0] + foo.size());//process all elements
bar(&foo[0], &foo[0] + foo.size()/2);//process first half elements
bar(&foo[0], &foo[0] + N); //process first N elements(assumingN <=foo.size())
bar(&foo[0]+foo.size()/2, &foo[0]+foo.size());//process second half elements