1

I am pretty new to C++ coding and got a question in C++ primer 5th edition Ex 3.42 which asked me to initialize an array with the elements of a vector .

So , i wrote thus code but am not able to understand why is begin function throwing an error of no matching function to call .

I also tried to correct the code by removing the begin function and initializing *pbeg with arr ,

like this ,

int *pbeg = arr ;

And it works .
Can someone please explain why and what am i doing wrong by using begin ?

#include <iostream>
#include <vector>
#include <iterator>

using std::cin ;
using std::cout ;
using std::endl ;
using std::vector ;
using std::begin ;

int main()
{
    vector<int> ivec ;
    int i ;

    while(cin >> i)
        ivec.push_back(i) ;
    const auto len = ivec.size() ;
    int arr[len] , *pbeg = begin(arr) ;  // here it shows the error 
    for(auto c : ivec)
    {
        *pbeg = c ;
        ++pbeg ;
    }
    for(auto c : arr)
        cout << c << "," ;
    cout << endl ;
    return 0 ;
}
  • 1
    Why do you want to use a [VLA (`int arr[len]`)](https://stackoverflow.com/questions/1887097/why-arent-variable-length-arrays-part-of-the-c-standard) here instead of a `vector`? And why do you want to use `begin`? – Lukas-T Jul 19 '20 at 14:57
  • 1
    You are trying to use a Variable length array (VLA), namely `int arr[len]`. This is not a feature of standard C++; some compilers accept it as a non-standard extension. `std::begin` works with standard arrays, but not with VLA. – Igor Tandetnik Jul 19 '20 at 14:57
  • @churill Since the vector is of variable length i thought if during runtime whatever be the size of the vector can be used to create a same sized array and then copy the vector's contents one by one . Also i used begin as i was learning that begin is used to return the address of the 1st element of an array but when i used it here the compiler throwed an error . So i wanted to understand why it did so ? – souvik mandal Jul 19 '20 at 15:04
  • @IgorTandetnik why cant i just store the size of the vector in a different variable , namely here , `len` which is a const type and use it to declare an array in C++ ? And the whole code works when i make some change at the place i used `begin()` as i mentioned on the post earlier . – souvik mandal Jul 19 '20 at 15:08
  • @souvikmandal Why not copy the vector to another vector? There's no reason at all to use an array. – john Jul 19 '20 at 15:08
  • @souvikmandal Why do you need to make a copy of the vector in the first place? If you want to print the vector then do it like this `for(auto c : ivec) cout << c << "," ; cout << endl ;` – john Jul 19 '20 at 15:10
  • 1
    You can't just do what you describe because what you describe is not part of the C++ language. Some variation of what you describe works with your particular compiler, because your compiler supports certain non-standard extensions to the language, and therefore accepts certain programs that are not in fact valid C++ programs. – Igor Tandetnik Jul 19 '20 at 15:10
  • @john it was an exercise question which asked to initialize an array with the elements of a vector . I have mentioned the book name and exercise no. in the post above . – souvik mandal Jul 19 '20 at 15:11
  • @IgorTandetnik i am quoting this from the book "C++ primer 5th edition" `string strs[get_size()]; // ok if get_size is constexpr, error otherwise` why will this not be a kind of VLA ? I am really new to this , Please explain . – souvik mandal Jul 19 '20 at 15:14
  • @souvikmandal Well you could fix your code just by writing `*pbeg = arr;` As already pointed out begin doesn't seem to work with a VLA. Is your book teaching you to use VLAs? It's not teaching you C++ if it is. – john Jul 19 '20 at 15:14
  • 2
    If you found this code in a book, then that book doesn't teach standard C++. – Igor Tandetnik Jul 19 '20 at 15:15
  • @IgorTandetnik C++ Primer is a good book, it's on our [recommended book list](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list), so I think the OP can't have been reading it correctly. – john Jul 19 '20 at 15:16
  • 1
    @souvikmandal Because it's a `constexpr`. An array size in C++ must be a constant. – john Jul 19 '20 at 15:17
  • @john It is possible the code shown is not in fact a direct quotation from the book. I don't have a copy to check. – Igor Tandetnik Jul 19 '20 at 15:18
  • @john `const auto len = ivec.size() ; int arr[len] ;` why is this wrong ? – souvik mandal Jul 19 '20 at 15:22
  • 2
    In standard C++, an array dimension must be a compile-time constant. Whereas `ivec.size()` can only be known at runtime. In standard C++, `std::vector` should be used where an array with a dynamic (known only at runtime) size is desired. – Igor Tandetnik Jul 19 '20 at 15:25
  • @IgorTandetnik Thank you very much !! I assumed array dimension to be just a constant but infact it is a compile time constant . Just one more doubt though why does my code work after changing `*pbeg =begin(arr);` to `*pbeg = arr ;` ? – souvik mandal Jul 19 '20 at 15:28
  • 1
    It works because your compiler supports VLA - a non-standard extension to the C++ language that allows arrays with known-at-runtime dimensions, and supports some but not all operations on such arrays. – Igor Tandetnik Jul 19 '20 at 15:30
  • @IgorTandetnik Okay . I use g++ compiler following ISO C++14 standards and i code in codeblocks . Should i in any case change my compiler or is everything fine ? – souvik mandal Jul 19 '20 at 15:34
  • [This question](https://stackoverflow.com/questions/31710642/disable-variable-length-automatic-arrays-in-gcc) discusses how to disable VLA in GCC, if that's what you want to do. – Igor Tandetnik Jul 19 '20 at 15:36

1 Answers1

0

Adding to what some of the commentators have already pointed out, essentially your problem boils down to this: the size of an array must be known at compile time. If it's not known then you'd use an std::vector or a dynamically allocated C-style array.

However, since this is a HW question, the following might give you some idea:

#include <iostream>
#include <vector>
#include <memory>

int main(void)
{
    std::vector<int> vec = {1, 2, 3, 4, 5};
    std::unique_ptr<int []> dyn_arr = std::make_unique<int []>(vec.size());
    auto arr_size = vec.size();

    for (auto i = 0; i < arr_size; i++)
    {
        dyn_arr[i] = vec[i];
    }

    for (auto i = 0; i < arr_size; i++)
    {
        std::cout << dyn_arr[i] << "\t";
    }

    std::cout << "\n";

    return 0;
}

Note: I've used unique_ptr to an int[] so that the memory management part is offloaded to the the language.

 valgrind ./dyn_array
==280== Memcheck, a memory error detector
==280== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==280== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==280== Command: ./dyn_array
==280==
==280== error calling PR_SET_PTRACER, vgdb might block
1       2       3       4       5
==280==
==280== HEAP SUMMARY:
==280==     in use at exit: 0 bytes in 0 blocks
==280==   total heap usage: 4 allocs, 4 frees, 76,840 bytes allocated
==280==
==280== All heap blocks were freed -- no leaks are possible
==280==
==280== For counts of detected and suppressed errors, rerun with: -v
==280== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)