I have made a recursive way of printing all of the elements of a vector, but it returns nonsense! and it throws a really strange exception:
Exception thrown: read access violation.
std::vector<int,std::allocator<int> >::operator[](...) returned nullptr.
And it outputs: 12358000
This is the code. What is the mistake I have made?
#include <iostream>
#include <vector>
using namespace std;
int printVec(vector<int>* foo) {
if ((*foo).empty())
return 0;
else {
cout << (*foo)[0];
printVec(foo + 4);
}
}
int main() {
vector<int> ref{ 1,2,3,4,5,6,7,8,9,0 };
printVec(&ref);
}
foo is a pointer to a std::vector<int>.
foo + 4 is adding 4 lots of sizeof(std::vector<int>) to foo in pointer arithmetic. There is not a std::vector at that location, so the behaviour of printVec(foo + 4) is undefined.
The expression (*foo)[0] is calling the overloaded [] operator on a std::vector which access the first element in the vector. If there is no element at that position then the behaviour of the program is undefined.
What is the mistake I have made?
You are using a pointer to a single vector and treat it as if it points into an array of std::vector<int>. It is only allowed to increment pointers that point to elements in arrays (actually you are allowed to get a pointer one past an object, but not more). A single std::vector is not an array and your code invokes undefined behavior by incrementing foo here: printVec(foo + 4);.
If you want to "point to" elements of the vector use iterators:
#include <iostream>
#include <vector>
using namespace std;
template <typename IT>
void printVec(IT current, IT end) {
if (current == end) return;
else {
cout << *current;
printVec(current+1,end);
}
}
int main() {
vector<int> ref{ 1,2,3,4,5,6,7,8,9,0 };
printVec(ref.begin(),ref.end());
}
What is the structure of a std::vector?
You need not know nor care. If you want to iterate elements use iterators. If you want to access the underlying array use .data().
Related
I'm having problems with a program that only accepts arrays. I'm having plenty of pointers to different arrays, but using *p seems to only give me the first element of the array. I want to return all the elements of the array. I know the length of the array, if that helps.
#include <typeinfo>
#include <iostream>
int i[10];
int* k=i;
cout<<typeid(i).name()<<'\n';
cout<<typeid(*k).name()<<'\n';
results in 'int [10]' and 'int' respectively. I want some way of returning k as 'int [10]'.
Your k is a pointer to int. It points to the first element of the array. If you want a pointer to the whole array then you need to declare it as such.
#include <typeinfo>
#include <iostream>
int main() {
int i[10];
int* k=i;
int(*p)[10] = &i;
std::cout<<typeid(i).name()<<'\n';
std::cout<<typeid(*k).name()<<'\n';
std::cout<<typeid(*p).name()<<'\n';
}
Output:
A10_i
i
A10_i
However, as others have said, std::array is much less confusing to work with. It can do (almost) anything a c-array can do without its quirks.
Certainly there is a solution to your actual problem that does not require to get the array from a pointer to a single integer.
Example to show you how much more convenient C++ array/vector is then "C" style arrays with pointers :
#include <vector>
#include <iostream>
// with std::vector you can return arrays
// without having to think about pointers and/or new
// and your called cannot forget to call delete
std::vector<int> make_array()
{
std::vector<int> values{ 1,2,3,4,5,6 };
return values;
}
// pass by reference if you want to modify values in a function
void add_value(std::vector<int>& values, int value)
{
values.push_back(value);
}
// pass by const refence if you only need to use the values
// and the array content should not be modified.
void print(const std::vector<int>& values)
{
// use range based for loops if you can they will not go out of bounds.
for (const int value : values)
{
std::cout << value << " ";
}
}
int main()
{
auto values = make_array();
add_value(values, 1);
print(values);
std::cout << "\n";
std::cout << values.size(); // and a vector keeps track of its own size.
return 0;
}
I am new to C++ concepts,I am very much confused in inserting a value in a nested container.
#include<bits/stdc++.h>
using namespace std;
int main()
{
vector<vector<vector<vector<vector<int>>>>>s;
s[0][0][0][0].push_back(5);
return 0;
}
My program gets terminated abnormally.
You've default initialised s. The default constructor of vector creates an empty vector.
s[0] accesses the first element of the vector. An empty vector has no elements. This is a contradiction. The behaviour of accessing elements outside the bounds of the vector is undefined.
You could initialise a non-empty vector for example like this:
std::vector<std::vector<std::vector<std::vector<std::vector<int>>>>> s
{ // std::vector<std::vector<std::vector<std::vector<std::vector<int>>>>>
{ // std::vector<std::vector<std::vector<std::vector<int>>>>
{ // std::vector<std::vector<std::vector<int>>>
{ // std::vector<std::vector<int>>
{5}, // std::vector<int>
},
},
},
};
You have to insert elements to each vectors before accesing. Otherwise, you will wrongly access to a nonexistent element.
#include <vector>
using std::vector;
int main()
{
vector<vector<vector<vector<vector<int>>>>>s;
s.push_back(vector<vector<vector<vector<int>>>>());
s[0].push_back(vector<vector<vector<int>>>());
s[0][0].push_back(vector<vector<int>>());
s[0][0][0].push_back(vector<int>());
s[0][0][0][0].push_back(5);
return 0;
}
Either stick with vector and follow eerorika's suggestion or choose a container default-constructing elements upon access, like std::map:
#include <map> // don't use stdc++.h or using namespace std
int main()
{
template<class T>
using map = std::map<std::size_t, T>;
map<map<map<map<map<int>>>>> s;
s[0][0][0][0][0] = 5;
}
Vectors size dynamically, so why is this giving a seg fault:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main(){
vector<int> vectorOfInts;
vectorOfInts[0] = 3;
}
What I'm trying to actually do is declare a vector in a class.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Directory{
public:
string name;
int maxIndex;
vector<Directory> subDirectories;
void addSubdirectory(string x){
Directory newSubdirectory(x);
subDirectories[maxIndex++] = newSubdirectory;
}
Directory(string x){
name = x;
maxIndex = 0;
}
};
int main(){
Directory root("root");
root.addSubdirectory("games");
}
But this also gives a seg fault.
Vectors don't resize entirely automatically. You use push_back or resize to change the size of a vector at run-time, but the vector will not automatically resize itself based on the index you use--if you index beyond its current size, you get undefined behavior.
In your demo code, you could do something like this:
vector<int> vectorOfInts(1);
vectorOfInts[0] = 3;
Alternatively, since you're just adding 3 to the end of the existing data (or nonexistent data, in this case) you could just use push_back (or emplace_back):
vector<int> vectorOfInts;
vectorOfInts.push_back(3);
It looks like the same basic approach will work with your real code as well. It also simplifies things a bit, since you don't need to explicitly track the maxIndex as you've done.
A default-constructed vector has no elements (i.e. its size() returns zero).
The operator[] does not check if it is supplied a valid index, and gives undefined behaviour if supplied an invalid index. It does not resize the vector. A vector with size zero has no valid indices.
That combination explains your problem.
The seg fault, come from the fact that you try to acces an element that does not exist. When you use operator [ ], be sure that you already alocate memory for this element using resize, push_back, emplace_back...
To make your code work, just replace this
void
addSubdirectory(string x)
{
Directory newSubdirectory(x);
subDirectories[maxIndex++] = newSubdirectory;
}
by
void
addSubdirectory(string x)
{
subDirectories.emplace_back(x); // c++11
// else subDirectories.push_back(Directory(x));
}
and you don't need the maxIndex, you can have it using the size method: subDirectories.size() - 1.
The code below is just the isolated problem. I want to not only reserve the size of the vector but also initialize the contents so that if a vector element within the size range is suddenly assigned a value, it won't throw a vector subscript out of range error. I'm basically replacing a fixed-size array that is used throughout a large amount of code and I want the same functionality without having to add "item.push_back(newItem)" to throughout the file. I tried putting a for loop inside the Node constructor that just added but for some reason the .push_back() method was unrecognized.
How would I not only reserve the size, but also initialize the contents within the constructor?
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
using std::cout;
using std::endl;
using std::string;
using std::vector;
int maxSize = 3;
struct Item{
string key;
string value;
};
struct Node{
int count;
vector<Item> items;
Node()
{
items.reserve(maxSize + 1);
}
};
int main(int argc, char *argv[])
{
Item item;
item.key = "Hi";
item.value = "there";
Node *p = new Node();
p->items[1] = item; // Error: vector subscript out of range
cout << p->items[1].key << " " << p->items[1].value << endl;
return 0;
}
Reserving only allocates underlying memory, for purposes of optimisation. If you don't know you need it, you don't. If you don't know you need it, and you wrote it, you shouldn't have done.
What you're trying to do is make the vector actually take on a size, and fill up with elements that you can immediately access via operator[].
To do so, write resize instead of reserve.
In fact, since you're doing so on a member in the constructor of its container, what you really should be doing is initialising the vector by calling its proper constructor:
struct Node
{
int count;
vector<Item> items;
Node()
: items(maxSize + 1)
{}
};
You're looking for resize instead of reserve
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;
}