I am new to C++. Say I have the following code:
vector<int> vec;
vec.push_back(5);
int x = vec.at(0);
From my understanding, x now represents a reference to the value in the vector. If this is the case, then why is it that if I were to have x = 7, the value in the vector would still be 5?
I tried searching on the site for a relevant thread, but did not see any that answered the question.
int x declares an integer. It is not a reference. In your code a copy is made of the value in the vector.
If you want a reference then you need to declare x as a reference to int:
#include <iostream>
#include <vector>
int main() {
std::vector<int> v{42};
int& x = v.at(0);
x = 5;
std::cout << v.at(0);
}
For further reading I suggest you pick a book and cppreference can be recommended very much https://en.cppreference.com/w/cpp/language/reference.
Related
Are these 2 statements std::vector<int> V(N) and std::vector<int> V[N] equivalent??
Also what do they mean?
std::vector<int> V(N) creates an std::vector<int> of size N.
std::vector<int> V[N] creates an array of size N containing std::vector<int>.
You can see this from this piece of code :
#include <vector>
#include <iostream>
#include <typeinfo>
const int N = 100;
int main()
{
std::vector<int> test(N);
std::cout << test.size() << '\n';
std::cout << typeid(test[0]).name() << '\n'; //output i
int i=1; test[0] = i; //runs fine
//std::vector<int> i2; test[0] = i2; //converting error
std::vector<int> test2[N];
std::cout << sizeof(test2)/sizeof(test2[0]) << '\n';
std::cout << typeid(test2[0]).name();
//int i3=1; test2[0] = i3; //converting error
std::vector<int> i4; test2[0] = i4; //runs fine
}
Result:
100
i
100
St6vectorIiSaIiEE
Edit: As #463035818_is_not_a_number and #Eljay mentioned, std::vector<int> V[N] should be written as std::array<std::vector<int>,N> for clarity.
The answer to this question comes in two parts. The first concerns basic syntax, and the second concerns semantics for the std::vector container. One of them is built into the language itself, the other is declared as part of the standard library.
Part 1:
Are these 2 statements std::vector V(N) and std::vector V[N] equivalent??
No. It appears you're confusing built-in array declaration syntax (i.e. the [] brackets), with the "array-like" semantics of the library-declared std::vector<T> object. It might help to recognize that under the hood, std::vector<T> is going to be declared as a struct or class. In a very rough sense, it will look something like this:
template<typename T>
struct vector {
vector();
vector(size_type count);
...
T *storage;
size_type count;
};
Here you see it will have a few different constructors, including one that takes a size_type and pre-allocates memory to store enough elements. A full list of the available constructors for std::vector can be found here.
The () syntax in your example is a call to a constructor, the behavior of which is implementation defined. The square bracket [] declaration syntax is a language feature that tells the compiler to allocate that many objects either on the stack or on the heap, depending on where the allocation occurs.
In most cases (I won't say never because there are always exceptions), you're not going to use std::vector<int> V[N] because std::vector<int> V is already a way to store an "array" of elements.
In the little program below, I wanted to be able to change the value inside M m by changing the value of s. But apparently I cannot do it. One way that would work would be to change the raw pointer but this is not safe:
#include <iostream>
#include <memory>
class M{
public:
std::shared_ptr<int> t;
};
std::shared_ptr<int> s;
int main() {
M m;
m.t = s;
s = std::make_shared<int>(5);
std::cout << m.t << std::endl; //prints 0
}
On this little program, I thought that by doing s = std::make_shared<int>(5), s's internal pointer would point to 5. However, what it does instead is substitute the value of s by another value, so m.t is not pointing to the new s.
Isn't it possible to do what I want?
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> nums {0,1,2};
vector<int> copy {0};
copy.at(0) = nums.at(0); // nums.at(0) returns a reference
nums.at(0) = -1; // why this line doesn't change copy[0]
std::cout << copy.at(0); // print 0
}
Hi, as code indicates, it looks like changing of nums.at(0) doesn't affect copy.at(0).
Does copy.at(0) = nums.at(0); call the copy-assignment operator a copy?
It doesn't make sense to me this line actually do a copy, because copy.at(0) also returns a reference.
References are bound on initialization. After that the reference refers to the bound object and cannot be made to refer to something else.
Maybe this is best understood by means of an example:
int x = 6;
int& x_ref = x; // bind x_ref to x
int y = 12;
x_ref = y; // assign the value of y to x
In your code copy.at(0) does return a reference, however you cannot rebind that reference to something else. Instead copy.at(0) = something; will assign something to what copy.at(0) references.
I fully agree to above the comments, you have misunderstood.
Also references must be initialized at the time of declaration,
This can possible illustrate your case.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> nums {0,1,2};
int& copy = nums.at(0);
nums.at(0) = -1;
std::cout <<"copy is"<< copy; // print -1
}
Be warned: this is asking for trouble, as soon as the vector reallocates or element is deleted, the reference will be dangling.
See also The concept of references in C++
Online demo
If I define a pointer to an object that defines the [] operator, is there a direct way to access this operator from a pointer?
For example, in the following code I can directly access Vec's member functions (such as empty()) by using the pointer's -> operator, but if I want to access the [] operator I need to first get a reference to the object and then call the operator.
#include <vector>
int main(int argc, char *argv[])
{
std::vector<int> Vec(1,1);
std::vector<int>* VecPtr = &Vec;
if(!VecPtr->empty()) // this is fine
return (*VecPtr)[0]; // is there some sort of ->[] operator I could use?
return 0;
}
I might very well be wrong, but it looks like doing (*VecPtr).empty() is less efficient than doing VecPtr->empty(). Which is why I was looking for an alternative to (*VecPtr)[].
You could do any of the following:
#include <vector>
int main () {
std::vector<int> v(1,1);
std::vector<int>* p = &v;
p->operator[](0);
(*p)[0];
p[0][0];
}
By the way, in the particular case of std::vector, you might also choose: p->at(0), even though it has a slightly different meaning.
return VecPtr->operator[](0);
...will do the trick. But really, the (*VecPtr)[0] form looks nicer, doesn't it?
(*VecPtr)[0] is perfectly OK, but you can use the at function if you want:
VecPtr->at(0);
Keep in mind that this (unlike operator[]) will throw an std::out_of_range exception if the index is not in range.
There's another way, you can use a reference to the object:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v = {7};
vector<int> *p = &v;
// Reference to the vector
vector<int> &r = *p;
cout << (*p)[0] << '\n'; // Prints 7
cout << r[0] << '\n'; // Prints 7
return 0;
}
This way, r is the same as v and you can substitute all occurrences of (*p) by r.
Caveat: This will only work if you won't modify the pointer (i.e. change which object it points to).
Consider the following:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v = {7};
vector<int> *p = &v;
// Reference to the vector
vector<int> &r = *p;
cout << (*p)[0] << '\n'; // Prints 7
cout << r[0] << '\n'; // Prints 7
// Caveat: When you change p, r is still the old *p (i.e. v)
vector<int> u = {3};
p = &u; // Doesn't change who r references
//r = u; // Wrong, see below why
cout << (*p)[0] << '\n'; // Prints 3
cout << r[0] << '\n'; // Prints 7
return 0;
}
r = u; is wrong because you can't change references:
This will modify the vector referenced by r (v)
instead of referencing another vector (u).
So, again, this only works if the pointer won't change while still using the reference.
The examples need C++11 only because of vector<int> ... = {...};
You can use it as VecPrt->operator [] ( 0 ), but I'm not sure you'll find it less obscure.
It is worth noting that in C++11 std::vector has a member function 'data' that returns a pointer to the underlying array (both const and non-const versions), allowing you to write the following:
VecPtr->data()[0];
This might be an alternative to
VecPtr->at(0);
which incurs a small runtime overhead, but more importantly it's use implies you aren't checking the index for validity before calling it, which is not true in your particular example.
See std::vector::data for more details.
People are advising you to use ->at(0) because of range checking. But here is my advise (with other point of view):
NEVER use ->at(0)! It is really slower. Would you sacrifice performance just because you are lazy enough to not check range by yourself? If so, you should not be programming in C++.
I think (*VecPtr)[0] is ok.
I'm fairly new to C++ especially STL. I'm trying to pass a vector as argument to a function, but it causes the application to crash. I'm using Code::Blocks and MingW. Here is a simple code.
#include <iostream>
#include <vector>
using namespace std;
void foo(const vector<int> &v)
{
cout << v[0];
}
int main(){
vector<int> v;
v[0] = 25;
foo(v);
return 0;
}
Thanks!
It crashes because you write past the end of the vector with v[0] - that's undefined behaviour. Its inital size is 0 if you do nothing. (You subsequently read the same too, but all bets are off well before that point).
You probably wanted to do:
vector<int> v;
v.push_back(25);
foo(v);
Or maybe:
vector<int> v(1);
v.at(0) = 25;
foo(v);
If you use v.at(n) instead of the [] operator you will get exceptions thrown rather than undefined behaviour.