I have this code:
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector <bool> v;
cin >> v[0];
return 0;
}
Why can't I do that? The compiler won't compile that, but I have other variable types in the vector, it will work just fine. What's the problem with this?
It's because std::vector<bool> is a specialization and doesn't act like a vector at all. This is widely recognized to be a major flaw in the Standard.
In order to save memory, vector<bool> stores each element as a single bit. But bits aren't individually addressable, so operator[] can't return a bool& reference connected to a bit. Instead it returns vector<bool>::reference... and cin doesn't provide function overloads to deal with this.
(juanchopanza correctly points out that your vector didn't have an element zero. But even if it did via resize or other mechanism, the fact that operator[] doesn't return a reference still gets in the way.)
At the time you call v[0], the vector has zero size, so you are accessing out of bounds. This is undefined behaviour.
Furthermore, std::vector<bool> is a specialization which has strange behaviour due to the fact that it does not hold individual bool elements. Its operator[] returns a kind of proxy object, the call to that operator may not do what you expect. It should be used with care, or not used at all.
You can solve the problem by reading a value into a local variable and then pushing it into the back of the vector, as in this working example (similar live demo here):
#include <vector>
#include <iostream>
int main()
{
std::vector<bool> v;
std::cout << std::boolalpha;
v.push_back(true);
std::cout << v[0] << std::endl;
bool b;
cin >> b;
v[0] = b;
std::cout << v[0] << std::endl;
}
This should work:
#include <iomanip>
...
bool a;
cin >> boolalpha >> a;
v.push_back(a);
(In addition to the problem mentioned by Ben Voigt, your current code isn't safe with types other than bool because your vector is empty when you're accessing v[0].)
Related
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 have a class called test with which I want to associate a large vector with in the order of million elements. I have tried doing this by passing a pointer to the constructor:
#include <iostream>
#include <vector>
using namespace std;
class test{
public:
vector<double>* oneVector;
test(vector<double>* v){
oneVector = v;
}
int nElem(){return oneVector->size();}
};
int main(){
vector<double> v(1000000);
cout << v.size() << endl;
vector<double>* ptr;
test t(ptr);
cout << t.nElem()<< endl;
return 0;
}
However, this results in a Segmentation Fault:11, precisely when I try to do t.nElem(). What could be the problem?
This is C++, don't work with raw pointers if you don't absolutely need to. If the goal is to take ownership of a std::vector without copying, and you can use C++11, make your constructor accept an r-value reference, and give it sole ownership of the std::vector that you're done populating with std::move, which means only vector's internal pointers get copied around, not the data, avoiding the copy (and leaving the original vector an empty shell):
class test{
public:
vector<double> oneVector;
test(vector<double>&& v):oneVector(std::move(v)){
}
int nElem(){return oneVector.size();}
};
int main(){
vector<double> v(1000000);
cout << v.size() << endl;
test t(std::move(v));
cout << t.nElem()<< endl;
return 0;
}
If you really want a pointer to a vector "somewhere else", make sure to actually assign ptr = &v; in your original code. Or new the vector and manage the lifetime across test and main with std::shared_ptr. Take your pick.
ptr is not initialized. What you "want" to do is:
test t(&v);
However, I think you'd be better suited with references here (it's in the title of your question after all!). Using references avoids unnecessary syntax (like -> over .) which just unnecessarily hinder the reading of the code as written.
class test
{
std::vector<double>& oneVector;
public:
test(vector<double>& v) : oneVector(v) {}
size_t nElem() const { return oneVector.size(); }
};
ptr is an uninitialized pointer. This unpredictable value gets copied to t.oneVector. Dereferencing it is undefined behavior.
You need your pointer to actually point at a valid vector.
You forgot to give your pointer the desired value, namely the address of the vector:
vector<double>* ptr = &v;
// ^^^^^^
In your code, ptr remains uninitialized, and your program has undefined behaviour.
Question is very easy but i forgot to use c++ and don't know where else to ask.
I have question regarding vectors in c++: when i make vector with objects and when i try to push_back new object on vector i get some wierd error. Can u help me and say how should i use push_back (on object?) so it works. Thanks!
I have .h class:
class x{
public:
x();
double cpuGHz;
int hddGB;
char brand[25];
};
and have main class:
#include "Racunalo.h"
#include <iostream>
#include <cstdlib>
#include <string.h>
#include <vector>
using namespace std;
int main()
{
int n,i;
double cpu;
int hdd;
char bra[25];
vector<Racunalo> vec;
Racunalo rac;
cin >> n;
for (i=0; i<n; i++)
{
cin >> bra;
cin >> hdd;
cin >> cpu;
strcpy(rac.brand, bra);
rac.hddGB = hdd;
rac.cpuGHz = cpu;
vec[i].push_back(rac); // this line is "rotten"
}
Replace
vec[i].push_back(rac);
with
vec.push_back(rac);
Good luck
vec[i].push_back(rac);
^^^^^^^
a reference to Recunalo object
vec[i] gives you an element of your vector (a reference to element), so you cannot push_back to it (unless it is object of class with push_back function). Here vec[i] refers to Racunalo object. std::vector::push_back is a member function of vector, so we call it on the object this way:
vec.push_back( rac);
^^^^
std::vector<Recunalo>
std::vector::push_back
Vector is just like an array except that it can grow dynamically.
push_back is a method that adds at the end of the container. If you create a vector like vector a(10) and then do a push_back you are inserting at the 11th place since all the first 10 places are initialized with 0. So, to be helpful it is ideal to create a vector like vector a, without any size, and then using push_back to insert at the end.
vector a;
a.push_back(5);
What is wrong with my code? I want to print out the array, but when I try to do so it seems to print out an address instead.
#include <iostream>
#include <ctime>
#include <stdlib.h>
using namespace std;
int main ()
{
srand(time(NULL));
int array[9]= {0};
for (int i=0;i<=8;i++)
{
array[i]= (rand()%101);
}
cout<< array;
system ("PAUSE");
return 0;
}
You can't just cout an array. Arrays are not cout-able. Whenever you successfully cout something of type T, it means that there's a dedicated overloaded << operator designed specifically to cout values of type T. And there's no dedicated << operator for cout-ing arrays (aside from strings). For this reason the compiler chooses the closest match for the given argument type: a << operator for pointers. Since arrays are convertible to pointers, that << is applicable here.
If you want to cout the values of all elements of your array, you'll have to either cout them manually, one by one, or use some standard algorithm that can do it for you. For example
std::copy(array, array + 9, std::ostream_iterator<int>(std::cout, " "));
You'll need to do a loop to output each array element on its own.
The problem is that C++ doesn't always know the size of the array, so it can't default to outputting the whole thing as you would expect.
You need to iterate over the array and print each element like how you assigned value at each index. Since array decays to a pointer to the first element in the sequence, you are getting the address.
std::cout doesn't have an overload for int array[9], so this decays to a pointer (int*) and this is what you'll see displayed (something like 0x7fffe47142d0).
To print the ints in the array individually, you will need to use a loop construct (like the for- loop you are using for populating the array) and send each of the ints to std::cout in turn, perhaps with some whitespace to format them.
Once you get the hang of C++ and its standard library, you may want to investigate how to do this with std::copy(), but I suspect this is a bit advanced for your homework.
C++ decays array type to a pointer type when the value is passed as argument to a function. C++11 has std::array (and TR1 specifies std::tr1::array) which retains the size of the array. Here is your example modified to use std::array:
#include <array>
#include <iostream>
#include <ctime>
#include <stdlib.h>
template<typename T, std::size_t N>
std::ostream& operator<< (std::ostream& ostm, const std::array<T, N>& a)
{
for (auto const& x : a)
ostm << x << ' ';
return ostm;
}
int main ()
{
srand(time(NULL));
std::array<int, 9> array;
for (auto& x : array)
x = rand() % 101;
std::cout<< array << std::endl;
}
How to translate properly the following Java code to C++?
Vector v;
v = getLargeVector();
...
Vector getLargeVector() {
Vector v2 = new Vector();
// fill v2
return v2;
}
So here v is a reference. The function creates a new Vector object and returns a reference to it. Nice and clean.
However, let's see the following C++ mirror-translation:
vector<int> v;
v = getLargeVector();
...
vector<int> getLargeVector() {
vector<int> v2;
// fill v2
return v2;
}
Now v is a vector object, and if I understand correctly, v = getLargeVector() will copy all the elements from the vector returned by the function to v, which can be expensive. Furthermore, v2 is created on the stack and returning it will result in another copy (but as I know modern compilers can optimize it out).
Currently this is what I do:
vector<int> v;
getLargeVector(v);
...
void getLargeVector(vector<int>& vec) {
// fill vec
}
But I don't find it an elegant solution.
So my question is: what is the best practice to do it (by avoiding unnecessary copy operations)? If possible, I'd like to avoid normal pointers. I've never used smart pointers so far, I don't know if they could help here.
Most C++ compilers implement return value optimization which means you can efficiently return a class from a function without the overhead of copying all the objects.
I would also recommend that you write:
vector<int> v(getLargeVector());
So that you copy construct the object instead of default construct and then operator assign to it.
void getLargeVector(vector<int>& vec) {
// fill the vector
}
Is a better approach for now. With c++0x , the problem with the first approach would go by making use of move operations instead copy operations.
RVO can be relied upon to make this code simple to write, but relying RVO can also bite you. RVO is a compiler-dependent feature, but more importantly an RVO-capable compiler can disable RVO depending on the code itself. For example, if you were to write:
MyBigObject Gimme(bool condition)
{
if( condition )
return MyBigObject( oneSetOfValues );
else
return MyBigObject( anotherSetOfValues );
}
...then even an RVO-capable compiler won't be able to optimize here. There are many other conditions under which the compiler won't be able to optimize, and so by my reckoning any code that by design relies on RVO for performance or functionality smells.
If you buy in to the idea that one function should have one job (I only sorta do), then your dilema as to how to return a populated vector becomes much simpler when you realize that your code is broken at the design level. Your function really does two jobs: it instantiates the vector, then it fills it in. Even with all this pedantary aside, however, a more generic & reliable solution exists than to rely on RVO. Simply write a function that populates an arbitrary vector. For example:
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
template<typename Iter> Iter PopulateVector(Iter it, size_t howMany)
{
for( size_t n = 0; n < howMany; ++n )
{
*(it++) = n;
}
return it;
}
int main()
{
vector<int> ints;
PopulateVector(back_inserter(ints), 42);
cout << "The vector has " << ints.size() << " elements" << endl << "and they are..." << endl;
copy(ints.begin(), ints.end(), ostream_iterator<int>(cout, " "));
cout << endl << endl;
static const size_t numOtherInts = 42;
int otherInts[numOtherInts] = {0};
PopulateVector(&otherInts[0], numOtherInts);
cout << "The other vector has " << numOtherInts << " elements" << endl << "and they are..." << endl;
copy(&otherInts[0], &otherInts[numOtherInts], ostream_iterator<int>(cout, " "));
return 0;
}
Why would you like to avoid normal pointers? Is it because you don't want to worry about memory management, or is it because you are not familiar with pointer syntax?
If you don't want to worry about memory management, then a smart pointer is the best approach. If you are uncomfortable with pointer syntax, then use references.
You have the best solution. Pass by reference is the way to handle that situation.
Sounds like you could do this with a class... but this could be unnecessary.
#include <vector>
using std::vector;
class MySpecialArray
{
vector<int> v;
public:
MySpecialArray()
{
//fill v
}
vector<int> const * getLargeVector()
{
return &v;
}
};