G
goodbyeera
1. Does std::vector has any chance to shrink its capacity?
My understanding of the member functions relating to capacity:
reserve(): will only reallocate when the passed in argument is larger
than current capacity
insert(): will only reallocate when size is about to exceed current
capacity
erase(): will only invalidate iterators pointing to elements after the
erased one, so it cannot reallocate, quotes from standard:
resize(): simply call insert() or erase(), so won't reallocate
So, if we don't take operator=() and swap() into account, it seems
that during the lifetime of a vector, its capacity won't shrink
forever?
But the standard declares:
A vector is a kind of sequence that supports random access iterators.
In addition, it supports (amortized) constant time insert and erase
operations at the end; insert and erase in the middle take linear
time.
If its capacity won't shrink, then erase at the end operation should
be pure constant time, not just amortized constant time.
Could anyone tell me where my understanding goes wrong?
2. Why std:artition() requires its arguments to be bi-directional
iterator? Why isn't forward iterator enough?
partition(l, u, p)
m = l;
for i = [l, u]
if (p(*i))
swap(m++, i);
return m;
3. The standard says std::binary_search() only requires forward
iterator, and claims its complexity as below:
Complexity: At most log(last - first) + 2 comparisons.
So it seems that it only counts comparison as complexity, but ignores
the cost of advance operation when the iterator is just forward
iterator, but not random access iterator.
Based on the same assumption, why not std::reverse()/std::reverse_copy
() just requires forward iterator instead of bi-directional iterator,
after all, advance operation doesn't count? See below what standard
says about their complexity, respectively.
Complexity: Exactly (last - first)/2 swaps.
Complexity: Exactly last - first assignments.
4. Why the first two arguments of std::find_first_of() requires
forward iterator, but not just input iterator?
5. Difference between std::istream_iterator and
std::istreambuf_iterator?
template <class T, class charT = char, class traits =
char_traits<charT>, class Distance = ptrdiff_t>
class istream_iterator: public iterator<input_iterator_tag, T,
Distance, const T*, const T&>
{...};
template<class charT, class traits = char_traits<charT>>
class istreambuf_iterator: public iterator<input_iterator_tag, charT,
typename traits:ff_type, charT*, charT&>
{...};
Why the former has const modifier for the pointer and reference type,
while the latter doesn't?
6. Difference of argument type of std::generate() and
std::random_shuffle()?
Why the functor argument of the former is passed by value, while the
equivalent of latter is passed by reference? What's the rationale for
such difference?
My understanding is that pass-by-value functor cannot retain its usage
information (e.g. internal state change in the RNG), thus calling
std::generate() again with the same functor will generate the same
sequence of numbers.
Pass-by-reference functor doesn't have this problem, but on the other
hand, it prevents user from passing a temporary object.
It seems that it will be better to use a pass-by-value functor
argument and return the used functor as the function's return value,
just as what std::for_each() does.
7. The prototype of bsearch() is:
void *bsearch(const void *key, const void *base, size_t nmemb, size_t
size, int (*compar)(const void *, const void *));
The base argument is of type (void*) and the return value is of type
(void*). This seems to be of C-like style, which is for the sake of
ease of usage of the return value, such as the strchr() in C:
char *strchr(const char *s, int c);
But in C++, most of such functions have been changed to a pair of
overloaded functions:
const char* strchr(const char* s, int c);
char* strchr(char* s, int c);
So, why the same change is not done to bsearch()?
8. As for std::basic_ostream and std::basic_istream, why the << and >>
operation of bool, short, int, long are all defined as member
function, but only the equivalent of char is defined as non-member
function?
My understanding of the member functions relating to capacity:
reserve(): will only reallocate when the passed in argument is larger
than current capacity
insert(): will only reallocate when size is about to exceed current
capacity
erase(): will only invalidate iterators pointing to elements after the
erased one, so it cannot reallocate, quotes from standard:
resize(): simply call insert() or erase(), so won't reallocate
So, if we don't take operator=() and swap() into account, it seems
that during the lifetime of a vector, its capacity won't shrink
forever?
But the standard declares:
A vector is a kind of sequence that supports random access iterators.
In addition, it supports (amortized) constant time insert and erase
operations at the end; insert and erase in the middle take linear
time.
If its capacity won't shrink, then erase at the end operation should
be pure constant time, not just amortized constant time.
Could anyone tell me where my understanding goes wrong?
2. Why std:artition() requires its arguments to be bi-directional
iterator? Why isn't forward iterator enough?
partition(l, u, p)
m = l;
for i = [l, u]
if (p(*i))
swap(m++, i);
return m;
3. The standard says std::binary_search() only requires forward
iterator, and claims its complexity as below:
Complexity: At most log(last - first) + 2 comparisons.
So it seems that it only counts comparison as complexity, but ignores
the cost of advance operation when the iterator is just forward
iterator, but not random access iterator.
Based on the same assumption, why not std::reverse()/std::reverse_copy
() just requires forward iterator instead of bi-directional iterator,
after all, advance operation doesn't count? See below what standard
says about their complexity, respectively.
Complexity: Exactly (last - first)/2 swaps.
Complexity: Exactly last - first assignments.
4. Why the first two arguments of std::find_first_of() requires
forward iterator, but not just input iterator?
5. Difference between std::istream_iterator and
std::istreambuf_iterator?
template <class T, class charT = char, class traits =
char_traits<charT>, class Distance = ptrdiff_t>
class istream_iterator: public iterator<input_iterator_tag, T,
Distance, const T*, const T&>
{...};
template<class charT, class traits = char_traits<charT>>
class istreambuf_iterator: public iterator<input_iterator_tag, charT,
typename traits:ff_type, charT*, charT&>
{...};
Why the former has const modifier for the pointer and reference type,
while the latter doesn't?
6. Difference of argument type of std::generate() and
std::random_shuffle()?
Why the functor argument of the former is passed by value, while the
equivalent of latter is passed by reference? What's the rationale for
such difference?
My understanding is that pass-by-value functor cannot retain its usage
information (e.g. internal state change in the RNG), thus calling
std::generate() again with the same functor will generate the same
sequence of numbers.
Pass-by-reference functor doesn't have this problem, but on the other
hand, it prevents user from passing a temporary object.
It seems that it will be better to use a pass-by-value functor
argument and return the used functor as the function's return value,
just as what std::for_each() does.
7. The prototype of bsearch() is:
void *bsearch(const void *key, const void *base, size_t nmemb, size_t
size, int (*compar)(const void *, const void *));
The base argument is of type (void*) and the return value is of type
(void*). This seems to be of C-like style, which is for the sake of
ease of usage of the return value, such as the strchr() in C:
char *strchr(const char *s, int c);
But in C++, most of such functions have been changed to a pair of
overloaded functions:
const char* strchr(const char* s, int c);
char* strchr(char* s, int c);
So, why the same change is not done to bsearch()?
8. As for std::basic_ostream and std::basic_istream, why the << and >>
operation of bool, short, int, long are all defined as member
function, but only the equivalent of char is defined as non-member
function?