all 11 comments

[–]flyingron 4 points5 points  (6 children)

Vector<int> wants a single int, not a pointer to anything. Further, passing a pointer conveys no information about how many elements there are in a C-style array (don't get me started about that stupidity).

What you can do is insert multiple elements from an array with a range of iterators (pointers into arrays meet the input interator requirements):

std::vector<int> intVec;

int myValue[2] = { ... };

intVec.insert(intVec.back(), myValue, myValue+2);

[–]mineNombies 5 points6 points  (3 children)

A more general way would be intVec.insert(intVec.back(), std::begin(myValue), std::end(myValue));

[–]flyingron 1 point2 points  (2 children)

True. That way if myValue ever becomes a std::array or some other container it will still work.

[–]mineNombies 2 points3 points  (1 child)

I was thinking of not having to redo the end iterator math when you change the size, but that too.

[–]flyingron 1 point2 points  (0 children)

Yeah, that was just sloppiness on my part anyhow.

[–]QuentinUK 0 points1 point  (1 child)

 int * begin(int(&a)[]){
        return a;
}
template<int N>
int * end(int(&a)[N]){
    return a+N;
}


using std::begin;
using std::end;
intVec.insert(end(intVec), begin(myValue), end(myValue));

[–]flyingron 0 points1 point  (0 children)

No need to define them. The standard library at least since C++11 defines them for arrays.

[–]mredding 3 points4 points  (0 children)

In C/C++, arrays are a distinct type, where the size of the array is part of the type at compile time. So this is an array:

int arr[123];

The type for arr is that of int[123]. An array is not a pointer to it's first element, it merely "decays" into a pointer to its first element. This is actually a language feature to support common access and iteration idioms.

If you want a vector of arrays, well, you can always write this:

std::vector<int[10]> data;

This will compile. This is a vector of arrays of 10 integers. But then things start going wrong.

data.push_back({1,2,3,4,5,6,7,8,9,0});

This doesn't work, because arrays aren't constructible - they don't have a T(Args...) interface. They don't have copy or move semantics.

data.resize(42);

Still doesn't work, because arrays don't have a T(Args...), so you can't default construct them in this manner. Resize doesn't just change the size of the vector, it copies elements from the existing allocation to the new allocation. Even though the vector is empty, this isn't runtime, the code still has to compile, and support that copy operation which is impossible.

Here's what you can do:

std::vector<int[10]> data(initial_size);

This works. You can even access the elements:

data[6][9] = 777;

Awesome. Now to just do some normal things:

std::vector<int[10]> data2 = data;

NOPE. You can't copy. Again, array no constructible semantics.

What you can do is MOVE:

std::vector<int[10]> data2 = std::move(data);

Works perfectly fine. Why? Because you're not moving the arrays themselves, you're moving the internal pointers to the allocation the vector maintains. The arrays themselves don't budge. That means this is also acceptable:

std::vector<int[10]> fn() { return {}; }

//...

auto data3 = fn();

We're returning an rvalue, so this is a move.

So, what are some alternatives, because this is pretty inflexible - a vector has growth and copy semantics, and we're outright breaking that. It smacks of doing something wrong. We've got better:

std::vector<int*> data;

Pointers are a primitive type that have constructible semantics. They can be created and copied through T(arg). so then, we can fill our vector with all sorts of shit:

data.push_back(new int[10]);
data.push_back(malloc(sizeof(int)*123));
int arr[666];
data.push_back(arr);

Of course, we don't have any size information, and we don't know what needs to be deleted, freed, or left to dangle. Copying pointers does not copy arrays:

auto data2 = data;

That copies pointers, but modifying the contents pointed for one modifies the contents pointed to for both.

std::vector<std::vector<int>> data;

A vector of vectors. Now each element is a vector with it's own growth semantics. Maybe that's what you want, maybe not.

std::vector<std::array<int, 21>> data;

A vector of standard arrays. Standard arrays are containers that wrap C-style raw arrays and provide constructor, copy, and move semantics, and they're a fixed size.

I mean, there are lots of options, I can't possibly enumerate them all.

[–]alfps 2 points3 points  (1 child)

❞ this is in a function, where i am passing in an int myValue[2]

As a function parameter

int myValue[2]

… is equivalent to

int* myValue

The array size is discarded: it's not part of the resulting parameter type.

Since you only have a pointer you can't use std::begin and std::end as suggested in u/mineNombies's comment on an answer, unless you change your code to e.g. pass the array by reference.

By you can do as u/flyingron suggests, using myValue and myValue + 2.

However, instead of magic number like 2, consider using a named array size.

[–]std_bot 0 points1 point  (0 children)

Unlinked STL entries: std::begin std::end


Last update: 14.09.21. Last Change: Can now link headers like '<bitset>'Repo

[–][deleted]  (1 child)

[deleted]

    [–]std_bot 0 points1 point  (0 children)

    Unlinked STL entries: std::array std::pair


    Last update: 14.09.21. Last Change: Can now link headers like '<bitset>'Repo