Accessing an element of a vector created dynamically - c++

vector <int> * v = new vector <int>;
v -> push_back (1);
cout << v[0]<< endl; // error
Why can't I access the first element? I get this error
error: no match for 'operator<<' (operand types are 'std::ostream {aka std::basic_ostream}' and 'std::vector')|

Why would you allocate a vector with new? The main point of using vectors is to avoid having to use new.
vector<int> v;
v.push_back(1);
cout << v[0] << endl;
If for some strange reason you decide you really must use a pointer, then you can do
vector<int>* v = new vector<int>;
v->push_back(1);
cout << (*v)[0] << endl;
But really, allocating a vector with new makes little sense.
Perhaps you were a Java programmer before you tried C++? If so then don't try to program C++ in a Java style, they are very different languages. You will get into a horrible mess if you do.

Because v is pointer to vector, but not reference or vector itself. Therefore v[0] gives you not what you likely expect. It gives you vector object itself. For which there is no stream output operator<< defined. You must use (*v)[0].

It's very unlikely that you need to dynamically allocate a vector like this, but if you do have a pointer to a vector:
vector<int>* v = new vector<int>;
then the correct syntax to invoke the member functions is:
// dereferencing the pointer and then using the member functions
(*v).push_back(1);
cout << (*v)[0] << endl;
or
// using -> with the correct names of the member functions
v->push_back(1);
cout << v->operator[](0) << endl;

Related

c++: std::vector of std::vector inside a struct

I need to create a struct that sotres a
std::vector<std::vector<int>> that will contain 4 vectors of ints.
I tried the declaration I usually use for vector of vectors:
struct myStruct{
std::vector<std::vector<int>> myVector(4);
};
but, when I compile, I get this error:
myProgram.cpp:79:52: error: expected identifier before numeric constant
std::vector<std::vector<int>> myVector(4);
^
myProgram.cpp:79:52: error: expected ‘,’ or ‘...’ before numeric constant
I tried to declare the vector in the struct and then reserve 4 elements in the main(), in the following way:
struct myStruct{
std::vector<std::vector<int>> myVector;
};
int main(){
myStruct s;
s.myVector.reserve(4);
s.myVector[0].push_back(1);
return 0;
}
In this way it compiles without errors, but I get a segmentation violation as soon as I try to push_back.
What is the proper way to do this task? And why can't I use the first declaration to specify the size of myVector?
Thank you! :)
A default member initializer inside a class or struct must have an = token and/or {curly braces}.
std::vector<std::vector<int>> myVector{4};
[Note this would be trickier if the type were just std::vector<int>, since curly braces for a vector imply a sequence of elements. std::vector<int>{4} is a vector with size one whose one element is 4, not a vector of four zeroes. But here it's fine because {4} can't convert to std::initializer_list<std::vector<int>>, so that constructor overload isn't eligible, and the vector(size_type) constructor does win.]
The example program has undefined behavior because reserve does not change the size or create any elements. So s.myVector[0] is invalid since the vector is still empty. Remember, reserve is just a setup hint for the vector. Any valid program that uses reserve would still be valid if you removed all the reserve calls.
Using resize instead would do what you seem to mean: make the size of myVector equal to 4, by creating 4 empty element vectors. Then the push_back would add the number 1 to the first of those vectors, resulting in data {{1}, {}, {}, {}}.
int main(){
myStruct s;
s.myVector.resize(4);
s.myVector[0].push_back(1);
return 0;
}
struct myStruct {
std::vector<std::vector<int>> myVector{4};
};
int main() {
myStruct s;
s.myVector[0].push_back(1);
s.myVector[0].push_back(2);
s.myVector[0].push_back(3);
s.myVector[0].push_back(4);
s.myVector[1].push_back(11);
s.myVector[1].push_back(21);
s.myVector[1].push_back(31);
s.myVector[1].push_back(41);
cout << s.myVector[0][0] << " " << s.myVector[0][1] << " " << s.myVector[0][2] << " " << s.myVector[0][3] << " " << endl;
cout << s.myVector[1][0] << " " << s.myVector[1][1] << " " << s.myVector[1][2] << " " << s.myVector[1][3] << " " << endl;
return 0;
}
What is the proper way to do this task?
Hope this will answer your question.

Passing std::vector::data to function expecting type** (double pointer)

As the title describes, I am trying to pass the pointer to the data of a std::vector into a function expecting a double pointer. Take as an example the code below. I have an int pointer d which is passed to myfunc1 as &d (still not sure if call it the pointer's reference or what), where the function changes its reference to the beginning of an int array filled with 1,2,3,4. However, if I have a std::vector of ints and try to pass &(vec.data()) to myfunc1 the compiler throws the error lvalue required as unary ‘&’ operand. I have already tried something like (int *)&(vec.data()) as per this answer, but it does not work.
Just for reference, I know I can do something like myfunc2 where I directly pass the vector as reference and the job is done. But I want to know if it's possible to use myfunc1 with the std::vector's pointer.
Any help will be very much appreciated.
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::vector;
void myfunc1(int** ptr)
{
int* values = new int[4];
// Fill all the with data
for(auto& i:{0,1,2,3})
{
values[i] = i+1;
}
*ptr = values;
}
void myfunc2(vector<int> &vec)
{
int* values = new int[4];
// Fill all the with data
for(auto& i:{0,1,2,3})
{
values[i] = i+1;
}
vec.assign(values,values+4);
delete values;
}
int main()
{
// Create int pointer
int* d;
// This works. Reference of d pointing to the array
myfunc1(&d);
// Print values
for(auto& i:{0,1,2,3})
{
cout << d[i] << " ";
}
cout << endl;
// Creates the vector
vector<int> vec;
// This works. Data pointer of std::vector pointing to the array
myfunc2(vec);
// Print values
for (const auto &element : vec) cout << element << " ";
cout << endl;
// This does not work
vector<int> vec2;
vec2.resize(4);
myfunc1(&(vec2.data()));
// Print values
for (const auto &element : vec2) cout << element << " ";
cout << endl;
return 0;
}
EDIT: What my actual code does is to read some binary files from disk, and load parts of the buffer into the vector. I was having troubles getting the modified vector out of a read function, and this is what I came up with that allowed me to solve it.
When you write:
myfunc1(&(vec2.data()));
You are getting the address of a rvalue. The pointed int* is so a temporary that is destroyed right after the call.
This is why you get this error.
But, as #molbdnilo said, in your myfunc1() function, you are reassigning the pointer (without caring to destroy previously allocated memory by the way).
But the std::vector already manages its data memory on its own. You cannot and you must not put your hands on it.
What my actual code does is to read some binary files from disk, and load parts of the buffer into the vector.
A solution could be to construct your std::vector by passing the iterator to the beginning and the iterator to the end of the desired part to extract in the constructor's parameters.
For example:
int * buffer = readAll("path/to/my/file"); // Let's assume the readAll() function exists for this example
// If you want to extract from element 5 to element 9 of the buffer
std::vector<int> vec(buffer+5, buffer+9);
If the std::vector already exists, you can use the assign() member function as you already did in myfunc2():
vec.assign(buffer+5, buffer+9);
Of course in both cases, you have to ensure that you are not trying to access an out of bounds element when accessing the buffer.
The problem is that you cannot take the address of data(), since it is only a temporary copy of the pointer, so writing to a pointer to it makes not that much sense. And that is good that way. You DO NOT want to pass data() to this function since it would overwrite the pointer with a new array and that would break the vector. You can remove one * from the function and only assign to it and not allocate the memory there. This will work, but make sure to allocate the memory in the caller (with resize, just reserve will result un undefined behavior, since data() is only a pointer to the beginning of the valid range [data(), data() + size()). The range [data(), data() + capacity ()) is not necessary valid.

Access pointer methods of pointer vector

I'm not really sure how to phrase the question exactly correctly, but I've declared two vectors
std::vector<enemy*> enemies;
std::vector<hit_area *> effects;
these work and are fine, however I pass them to a function with
handleGame(strd_maps[0], &gcam, &mainchar, currentKeyStates, &enemies, &effects)
which works and is fine, however in the function, when I try to access members or methods or enemies or effect
if(effects[d]->collide(enemies[i]->x, enemies[i]->y enemies[i]->w, enemies[i]->h))
I get the error "base operand of "->" has non-pointer type 'std::vector*'.
I can access the size of both enemies and effects, it's just accessing the methods that is giving problems
Normally you don't pass the address of a vector. Instead, you pass a reference:
void func(std::vector<enemy*> &enemies) {
std::cout << enemies.size() << '\n';
std::cout << enemies[i]->x << '\n';
}
// Call it like:
func(enemies);
If you pass the address of the vector, then you need to use some slightly wacky syntax, like:
std::cout << enemies->operator[](i).x << '\n';
So always use refrence in case of vectors

Expression must have a pointer type error

I have read the other similar posts, but still haven't found a way to solve my coding problem.
Here is the code:
void Foo(vector<Name> &obj){
vector<Name> *temp = 0;
temp = new vector<Name>;
if (!temp){
std::cout << "temp Allocation Error!" << std::endl;
exit(1);
}
temp->push_back(obj[n]);
std::cout << temp[0]->member_function() << std::endl;
}
Foo is a universal function.
I have a function Foo that takes a reference to a vector container. Within Foo there is a dynamic vector called temp.
I use push_back() to insert an obj into the temporary vector.
Then I wish to access that obj stored in the temporary vector in order to access its member function.
However this is where the compiler says that "expression must have pointer type".
Could somebody please explain how to rewrite this line of code.
std::cout << temp[0]->member_function() << std::endl;
temp[0]->member_function()
This treats temp as if it were an array of pointers-to-vector, which it's not.
You need to dereference temp before performing array subscripting on the result:
(*temp)[0].member_function()
Honestly, though, dynamic allocation here is pointless and is giving you a memory leak right now.
You have a vector of Name objects, and not Name*, but you use the "->" operator instead of "." which is what the compiler is telling you.
You should either try:
std::cout << (*temp)[0].member_function() << std::endl;
or make the vector elements Name*.
temp[0]->member_function()
would be correct if temp were a vector of pointers, but it isn't – it's a pointer to one vector.
And you can't use -> with a vector.
(It is equivalent to (*temp)->member_function().)
You can say
(*temp)[0].member_function()
but the better solution is usually to avoid dynamic allocation completely:
vector<Name> temp;
temp.push_back(obj[n]);
std::cout << temp[0].member_function() << std::endl;

Creating an array of classes not working

I'm trying to create an array of classes using a vector, but I think I'm getting the syntax wrong from instantiating the array. The error I'm getting is:
error: request for member 'setX' in objects[0], which is of non-class type 'std::vector'
#include <iostream>
#include <vector>
using std::cout;
class A {
public:
void setX(int a) { x = a; }
int getX() { return x; }
private:
int x;
};
int main() {
std::vector<A> *objects[1];
objects[0].setX(5);
objects[1].setX(6);
cout << "object[0].getX() = " << objects[0].getX() << "\nobject[1].getX() = " << objects[1].getX() << std::endl;
}
std::vector<A> objects; // declare a vector of objects of type A
objects.push_back(A()); // add one object of type A to that vector
objects[0].setX(5); // call method on the first element of the vector
With an asterisk and a square brackets, you are declaring an array of pointers to vectors instead of a vector. With std::vector<T> you do not need square brackets or an asterisk:
std::vector<A> objects(2); // 2 is the number of elements; Valid indexes are 0..1, 2 is excluded
objects[0].setX(5); // This will work
objects[1].setX(6);
The reason the compiler thought that you were trying to call setX on a vector is that the square bracket operator, overloaded by the vector, is also a valid operator on an array or a pointer.
An array and std::vector are two completely different container types. An array is actually a fixed-size block of memory, where-as a std:vector object is a dynamic sequential container type, meaning it can be dynamically "grown" and "shrunk" at run-time, and the object itself manages the memory allocation of the objects it owns. Their apparent similarities are that both can access members in O(1) complexity and can use the bracket syntax for accessing members.
What you want is something like the following:
int main()
{
//make a call to the std::vector<T> cstor to create a vector that contains
//two objects of type A
std::vector<A> objects(2);
//you can now access those objects in the std::vector through bracket-syntax
objects[0].setX(5);
objects[1].setX(6);
cout << "object[0].getX() = " << objects[0].getX() << "\nobject[1].getX() = " << objects[1].getX() << std::endl;
return 0;
}
here what you did is define an array with 1 element of type std::vector*, you may want to read more about vector and array first.
The correct way to define it is:
std::vector<A> objects(2);
or using pointers if that is what you intend to
std::vector<A*> objects(2);
objects[0] = new A();
objects[1] = new A();