I apologize if this question has already been answered (I tried searching around, but couldn't find anything quite the same, and similar questions' solutions didn't work), but how do I pass an object (in this case, a vector of objects) and have the function edit those values without returning anything?
Example:
void incVector(std::vector<int> vec)
{
for (auto l = 0; l < int(vec.size()); l++)
{
vec[l]++;
}
}
int main()
{
std::vector<int> vec;
vec.push_back(1);
vec.push_back(2);
for (auto l = 0; l < int(vec.size()); l++)
{
std::cout << vec[l]; //Output: "12"
}
incVector(vec);
for (auto l = 0; l < int(vec.size()); l++)
{
std::cout << vec[l]; //Output: "12"
//This output should be "23"
}
}
Obviously, what I'm actually using this for is much more complex, but this is enough of an example to get the point of what I'm trying to do across. In the actual project, it's a rabbit hole of different functions, some of which return things while others don't, so having it simply return the vector isn't an option.
I have tried making incVector accept a reference to a vector, a pointer to a vector, a pointer to a reference to a vector, and a pointer to a pointer to a vector (which are solutions that seemed to work for other similar questions) but none of those are working for me.
EDIT:
God, I feel stupid. I swear I'd tried using a reference before and it didn't work. Yet now, trying it again works just fine. Sorry! ^^;
you pass the vector by value, thus modifications are purely local:
change prototype of your function to:
void incVector(std::vector<int> &vec)
to pass by reference and get the one from main modified
Take the argument by reference. You can also use a modern for-loop.
void incVector(std::vector<int>& vec)
{
for (auto& l : vec)
{
++l;
}
}
But you don't actually need to do any of this. Applying an operation on each element of the vector can be done easily using a standard algorithm (std::for_each) and a lambda function that takes a reference to the vector's element:
#include <algorithm>
// ...
std::for_each(vec.begin(), vec.end(), [](int& l){ ++l; });
for_each is going to call the lambda for each element in the vector and pass it as the argument. Since you take the argument by reference (int&), incrementing it will increment the actual element contained in the vector.
The key point to take away from this however, is that when you want to give a new name to an object that already exists, you use a reference. Those are declared with & before their identifier:
int i = 0;
int &i_ref = i;
Here, i_ref is a reference to i, meaning it's just another name for i. Modifying i_ref is the same as modifying i.
The same applies to function arguments. If a function argument is a reference, it means it's another name for the object that was passed to the function. Modifying the reference is the same as modifying the object that was passed to the function.
Related
I am trying to create a sorting function with the parameters being a pointer of a list and I am trying to access an element of the given list. Hopefully this code speaks for the problem better than I can:
void bubbleSort(std::vector<int> *L) {
unsigned int i = 0; int temp;
while(isSorted(*L)) {
if(i==L->size()-1) {
i = 0;
}
if(i<L[i]/*<-ERROR here.*/) {
temp = L[i+1]; // ERROR HERE
L[i+1] = L[i]; // ERROR HERE
L[i] = temp; // ERROR HERE
}
}
}
You don't need to painfully dereference every individual use of L (and indeed doing so is error-prone, as you've demonstrated by missing one in your answer).
Instead, just write:
void bubbleSort(std::vector<int> *Lptr) {
auto &L = *Lptr;
and keep the rest of the code the same.
NB. It would be even better to change the function itself, to
void bubbleSort(std::vector<int> &L) {
as it should have been written in the first place, but I'm assuming there's some artificial reason you can't do that.
The function accepts a pointer to an object of type std::vector<int>.
void bubbleSort(std::vector<int> *L) {
To access the original vector using the pointer, you can write either *L or L[0]. That is, both expressions yield an lvalue reference of type std::vector<int> & to the vector.
To get the i-th element of the vector using the subscript operator through the pointer, you can write either (*L)[i] or L[0][i],
However, in this if statement:
if(i<L[i]/*<-ERROR here.*/) {
You are trying to compare the variable i of type unsigned int to the object L[i] of type std::vector<int>. When i is not equal to 0, this yields a non-existent object of the vector type.
It seems you mean something like the following instead:
if ( (*L)[i] < (*L)[i+1] ) {
or:
if ( L[0][i] < L[0][i+1] ) {
or, vice versa:
if ( L[0][i+1] < L[0][i] ) {
Depending on whether the vector is sorted in ascending or descending order.
Pay attention to the fact that there is no sense in declaring the parameter as a pointer to a std::vector<int>. The function would be much clearer and readable if it accepted the vector by reference instead:
void bubbleSort(std::vector<int> &L) {
In this case, the if statement would look like this:
if ( L[i] < L[i+1] ) {
Although I prefer to change the source code as other answer. But, for this question, you can use ->at() function to access the element in a vector pointer.
if(i<L->at(i)) {
temp = L->at(i+1);
L->at(i+1) = L->at(i);
L->at(i) = temp;
}
Say that I have a vector, v,
vector <int> v = {0,1,2,...n};
What is the proper way to loop through v in a function taking a pointer to v as an argument? I can see two ways, either dereference the vector using (*) or using the .at() member:
void foo(vector <int>* v)
{
for (auto& el : (*v))
bar(el);
}
or
void foo(vector <int>* v)
{
for (int k = 0; k < n; k++)
bar(v->at(k));
}
Is there any difference between the two? Or is there another, superior, way to do it? It seems to me the second one would dereference the full vector object each iteration to get a single value, which seems like a bit of an over-kill, surely it would be better to only dereference the value at the memory location you want?
Pointer will be dereferenced in both cases. However at performs range checking and throws an exception if it fails so second approach will be slower.
A proper approach may look like this:
void foo(::std::vector<int> & v)
{
for(auto & el: v)
{
bar(el);
}
}
Since your code assumes that pointer is always valid there is not a single reason to use it instead of a reference. See Cpp Core Guidelines.
I have a method, which i want to execute differently depending on if the passed variable is an element of a vector or not, like for example:
void method(int a){
if (/*a is an element of a vector*/) //do one thing
else //do another thing
}
and then in main:
vector<int> a;
a.pushback(1);
int b = 1;
method(a[0]); // does one thing
method(b); // does the other thing
What is the simplest way to do that?
Well, for all cases this is impossible, because it actually requires your function to look at how it is executed, and there is no such thing in C++. The hated eval() comes to mind.
But in a certain case, when your vector is a global entity, you could pass your variable by link instead of value. Then, you can check if it fits the space between the start and end of the desired vector. This is how it is done(not tested though, but should work)
vector<int> v;
//fill it somewhere somehow
void method(int& a)
{
int* beg = v.data();
int* end = beg + v.size();
int* val = &a;
if ((val >= beg) && (val < end))
{
//it is a part of vector
}
else
{
//it is not a part of vector
{
}
Problem is that you really shouldn't do it this way... As people in the comments said, it DOES look like an XY problem.
An int is an int. An int does not wear a label around its neck, telling everyone where it came from. When an int is passed to a function, there is nothing that specifies where the int originates.
You should take this as an opportunity to learn about iterators, and implement an overloaded method that takes either an
void method(int);
for a parameter, or a
void method(std::vector<int>::iterator iter);
for a parameter (or, perhaps, a const_iterator), and invoke the alternative method() by passing it an iterator to the int in your vector.
This is a noob question, sorry but, I just started using vectors in c++. Here's is the code I am struggling with.
int main()
{
//some code
int n;
cin>>n;
vector <int> a(n+1,0);
int first=find(&a,d); //d has some value from the upper portion of the code
}
int find(vector <int>* a,int o)
{
int b=o;
while(a->b!=0)
b=a->b;
return b;
}
Q1 : Why doesn't passing vector like find(a,d) work like it does in arrays.?
Q2 : In the find function, Why do I have to access the vector elements with "." or "->". Shouldn't a[b] work? If that is the correct way then why does a[b] work in the main function?
Q3 : What's wrong with the code? When I compile I get the error
In function ‘int find(std::vector<int>*, int)’:
error: ‘class std::vector<int>’ has no member named ‘b’
I understand the error, but then how do I access the required element?
Thanks in advance. :)
Why doesn't passing vector like find(a,d) work like it does in arrays.?
Arrays are passed by "decaying" into a pointer to the first element; so they are effectively passed by reference.
Vectors are straightforward object types, passed by value unless the function is declared to take a reference. A function taking it by value will get a separate copy of it.
You could change the function to take the vector by reference:
void find(const std::vector<int> & a, int o);
^
The const is optional, but is a very good idea if the function doesn't need to modify the vector.
In the find function, Why do I have to access the vector elements with "." or "->".
You don't. You access class members of the vector itself (such as size()) like that.
Shouldn't a[b] work?
It would if a were an object or reference. Since it's a pointer, you have to dereference it, (*a)[b]
If that is the correct way then why does a[b] work in the main function?
In the main function, 'a' is an object, so can be used directly as an operand.
You should study vectors, templates, the c++ way to do that.
Take a look at: http://www.cplusplus.com/reference/vector/vector/
Q1 : Why doesn't passing vector like find(a,d) work like it does in arrays.?
Because it is not an array, its an object, so you can pass it as copy and not referece, you just pass it as a reference if you change the value.
Q2 : In the find function, Why do I have to access the vector elements with "." or "->". Shouldn't a[b] work? If that is the correct way then why does a[b] work in the main function?
a[position] returns the element
a->b dont work, you cannot access the b as an element
Use a->at(position) to access every element in the vector
Example (you can use iterators too)
for(int x=0; x<a->size();x++)
cout << a->at(x);
Q3 : What's wrong with the code? When I compile I get the error
The previous question answers that.
You dont have the b element, the A is a vector it contains elements.
If you want to get the element at the position B do a->at(b).
If you want to find use
for(int x=0; x<a->size();x++)
if(a->at(x) == b) return x; //returns the position
You're saying:
int b = o;
while(a->b!=0)
b=a->b;
return b;
when you mean:
for(vector<int>::const_interator i = a.begin(); i != a.end(); ++i)
if (*a == o)
return a.end() - i;
return a.size();
Sorry about the confusing title, did not know what to title it.
I have this function:
static void smooth5(IntVector*& v)
{
IntVector* tmp = new IntVector();
for(int i=0; i<v->size(); i+=2)
tmp->push_back(v->at(i));
delete v;
v = tmp;
}
and in the main I do this:
IntVector* v = new IntVector();
v->push_back(0);
v->push_back(1);
v->push_back(2);
v->push_back(3);
smooth5(v);
//print the contents of v
When I print the contents of v, the output is 0 2.
But I did not understand what
IntVector*& v
really means when v is a pointer to an object on the heap. Can someone please explain?
IntVector*& declares a reference to a pointer. Using this as a function argument allows smooth5 to modify the caller's copy of v.
It is similar to but more readable than passing a pointer to a pointer - IntVector**.
In your example, smooth5 deletes the caller's IntVector and points it to its tmp variable instead.
This is not a pointer to reference but a reference to a pointer. This means that instead of passing a copy of the pointer to the function you pass a reference to it. So as a result any modifications you do to the pointer in the function smooth5 will affect the argument you pass to it in this case the pointer v.
What IntVector*& v in your code means depends who's reading it.
When the compiler reads it, it means that v is a reference to
a pointer to IntVector (which is a typedef to
std::vector<int>?). When I read it, it means that the author
of the code probably didn't understand how C++ works, and is
trying to adapt Java or C# idioms that aren't appropriate. The
idiomatic way of writing this would be:
void smooth5( IntVector& v )
{
IntVector results;
for ( int i = 0; i < v->size(); i += 2 ) {
results.push_back( v[i] );
}
v.swap( results );
}
Any code which involved pointers to vectors is highly
suspicious.