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;
}
Related
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().
As you can see, my code works fine, but I had a doubt about use of auto and int in the first loop while accessing a vector:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<vector<int>> a{{1,2,3},{4,5,6}};
//why don't work when i use int in the first loop,and why it work when i use auto
for(auto n:a)
{
for(int b:n)
{
cout<<b<<" ";
}
cout<<endl;
}
}
because in the first loop (the outer one), n type is an std::vector<int> not an int.
Note that a is a vector of vectors, hence its elements are vectors, not integers. And of course, the elements of each element of its elements are integers.
The range-based loop can be written explicitly as
for(vector<int> n:a)
Or even better
for(vector<int>& n:a)
to avoid copying
Or even more better
for(const vector<int>& n:a)//equivalent to for(const auto & n:a)
because you don't make a change to it
I'm trying to initialize a 2d vector of unique_ptrs to set it's sizes and each index to nullptr
or if i want to some Base class object pointer but it doesn't work.
#include <vector>
#include <memory>
class Base
{
}
int main()
{
int m_width = 150, m_length = 13;
vector <vector <std::unique_ptr<Base>>> m_board;
m_board(m_length, vector < std::unique_ptr<Base>(m_width, nullptr));
}
also tried this method and still nothing:
m_board(m_length, vector < std::unique_ptr<Base>(std::move(m_width, nullptr)));
and this way too:
m_board(m_length, vector < std::unique_ptr<Base>(std::move(std::make_unique(m_width, nullptr))));
still nothing is working yet, for now i use a very ugly function with two for loops to do it
but i'm sure there is a way to make this work by using the constructor of both vectors and unique_ptr..
any ideas?
First, if the std::vector is already constructed, to change the size of the vector is done by using std::vector::resize. Your code was mixing up construction with sizing an already constructed vector.
The second thing is that the second argument to the two-argument vector constructor (see (4)) is now an allocator for C++ 14 or greater, not the default value.
Thus the easiest way to set up the vector is to first resize the outer vector, and then resize each of the inner vector's in a loop individually:
#include <vector>
#include <memory>
#include <iostream>
class Base
{
};
int main()
{
int m_width = 150, m_length = 13;
// Create a vector with m_length size
std::vector<std::vector<std::unique_ptr<Base>>> m_board(m_length);
// individually resize the inner dimensions
for (auto& m : m_board)
m.resize(m_width);
}
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