How to transfer elements of 1 vector into another vector? - c++

I am learning C++ and decided to make a card deck system using vectors. I have been able to randomly shuffle it, make 1 singular deck, and now I want to make a function that deals a hand from that deck.
Say I wanted a hand of 10 cards from a deck of 52 cards, therefore 42 cards would be left and the first 10 cards of the Deck vector will be taken and placed into the newHand vector but after looking for solutions on how to approach this using erase() and pop_back(), I cant seem to find an efficient or proper solution. However since I am new to C++ my code might not be the best thing to look at so I am open for suggestions on how to make this better, maybe with pointers? (Pointers are confusing to me and I am not sure when to use them).
Here are the main functions:
void Deck::deleteElement(std::vector<std::string> Deck, int index)
{
while (index--) {
Deck.erase(Deck.begin(), Deck.begin() + index);
}
}
void Deck::dealHand(int numOfCards, std::vector<std::string>& currentDeck, int numOfDecks)
{
std::vector<std::string> newHand;
static int remaining = deckSize(numOfDecks);
while (numOfCards-- && remaining != 0) {
newHand.push_back(currentDeck[numOfCards]);
--remaining;
} deleteElement(currentDeck, numOfCards);
for (auto & i : newHand) {
std::cout << i << " ";
}
std::cout << ",there are now " << remaining << " cards remaining" << std::endl;
}
I want to mention that deleteElement when using erase gives me this error
malloc: *** error for object 0x16f9ddf40: pointer being freed was not allocated
malloc: *** set a breakpoint in malloc_error_break to debug
I also could not find much on explaining what this means, if anyone can that would be a great help.

I would probably not bother with actually erasing elements from the deck's internal vector. That's because you might want to reshuffle and deal cards multiple times over the course of a game, which is easier if you just keep them all in the deck and track which ones have been dealt. And since almost everything container-related uses iterators, you can keep it short and simple like this:
#include <iterator>
#include <vector>
class Card {};
class Deck {
public:
using Cards = std::vector<Card>;
// Just an example constructor
explicit Deck(std::size_t size = 52)
: m_cards(size), m_current{m_cards.begin()}
{}
Cards dealHand(std::size_t count) {
auto begin = m_current;
std::ranges::advance(m_current, count, m_cards.end());
return Cards(begin, m_current);
}
std::size_t
size() const { return std::ranges::distance(m_current, m_cards.end()); }
private:
Cards m_cards;
Cards::iterator m_current;
};
int main() {
Deck deck {};
auto hand = deck.dealHand(10);
return deck.size();
}
While it's not strictly necessary to use std::ranges functions (they have equivalents in the std namespace), this part of C++20 is now widely supported. One advantage is that range algorithms accept entire ranges (such as containers) instead of only pairs of iterators, for example std::ranges::shuffle.

Related

How do I create an array of objects?

I only know Java, and I am learning how to do c++ right now. I currently have an object called "node". I want to make an array of those elements in a different class, and I have to perform many operations on this array. Because of this, I am trying to declare a global array variable that gets initialized in my constructor. In Java, this would've been done by
ObjectName[] variableName = new ObjectName[size];
but I am not sure how to do it in c++. I've tried declaring it similar to how I declared the other global arrays, with
Node* nodes;
and then in my constructor:
nodes = new Node[size]
but I got a bunch of compiler errors. How am I supposed to do this? This is only my second week of coding in c++, so try to keep answers basic.
In C++ you use vector more often than array. You also distinguish between creating objects on the stack and on the heap (you already mentioned that concept; in C++ you are more actively involved in thinking about that).
You also may want to pay attention which C++ Standard you are using. Some concepts are not available in older standards. I tried to mention some in the example code below.
When dealing with arrays in C/C++ you should understand the notion of pointers, which I believe is the probable cause of your confusion. new creates an object on the heap and returns a pointer. When creating an array, then the returned pointer points to the first element.
Avoid new if you can. In newer C++ standards there are better concepts of smart pointers (e.g. std::unique_ptr<...>); I will not dive into that since you are just beginning. Be patient with learning C++, I am sure you will succeed, it takes time really.
#include <iostream>
#include <array>
#include <vector>
struct Node {
std::string name = "node";
};
int main() {
const size_t size = 10;
// you can create it on the stack
// will be deleted when leaving the block/scope
Node nodes1[size];
nodes1[0].name = "first node1";
std::cout << nodes1[0].name << std::endl;
// you can create it on the heap
// you have to delete the objects yourself then
Node *nodes2 = new Node[size];
nodes2[0].name = "first node2";
std::cout << nodes2[0].name << std::endl;
// in C++ 11 and later you can use std::array<...>
// you have to include the header <array> for that
std::array<Node, size> nodes3;
nodes3[0].name = "first node3";
std::cout << nodes3[0].name << std::endl;
// in C++ you use array "seldom"
// instead you use the containers quite a lot as far as I have learned
// e.g. you can include <vector>; can be used like an array
std::vector<Node> nodes4(size);
nodes4[0].name = "first node4";
std::cout << nodes4[0].name << std::endl;
// you can iterate over a vector like you know it from an array
for (size_t i = 0; i < nodes4.size(); ++i) {
if (i == 0) {
std::cout << nodes4[i].name << std::endl;
}
}
// in C++ you will soon learn about iterators too
for (auto iter = nodes4.begin(); iter != nodes4.end(); iter++) {
if (iter == nodes4.begin()) {
std::cout << iter->name << std::endl;
}
}
return 0;
}
How do I create an array of objects?
Given a type named ObjectName, you can define an array variable with name variableName and a compile time constant size size like this:
ObjectName variableName[size]{};

Array Size as Constructor Parameter

I am creating a C++ class which wraps an floating point 2d array and provides some additional functionality. I want to pass the array's shape as parameters to the constructor, see the code (the class Block part) below. The line ends with comment "// here" would cause error during compilation because _nx and _ny are not known at that time.
There are two solutions (I think) around this: one is using pointer (see solution 1 in the code below) and dynamically allocate the array; the other is using template (see solution 2 in the code below), but I have several reasons not to use them:
I don't want to use pointer as long as there is a pointer-less
option; in other words, I don't want to use new and delete. The
reason for this is a personal preference for purer c++.
I don't want
to use template because there can be many different block shapes - I
don't want the compiler to create many classes for each of them,
this is an overkill and increases the executable size.
In addition, I don't want to use stl vector because the array size is fixed after creation; also I am doing numerical computation, so a 'raw' array suits me much better.
I have searched in SO and there are five or six questions asking similar problems, there is no conclusion which one is better though, and none of them are from a numerical standing point so vector or new/detele are good answers for them - but not for me. Another reason I post this question is I want to know if I am too restrictive in using c++ features. As I will be using c++ extensively, it's very important to be aware of c++'s limitation and stop asking/searching too much for some feature that doesn't exist.
#include <iostream>
#include <memory>
using namespace std;
class Block
{
public:
Block(int nx, int ny):_nx(nx),_ny(ny){}
void Report(void)
{
cout << "Block With Size ["<<_nx<<","<<_ny<<"]\n";
}
private:
const int _nx, _ny;
double _data[_nx][_ny]; // here
};
/// Solution 1, using auto_ptr
class BlockAuto
{
public:
BlockAuto(int nx, int ny):_nx(nx),_ny(ny),_data(new double[_nx*_ny]){}
void Report(void)
{
cout << "BlockAuto With Size ["<<_nx<<","<<_ny<<"]\n";
}
private:
const int _nx;
const int _ny;
const auto_ptr<double> _data;
};
/// Solution 2, using template
template<unsigned int nx, unsigned int ny>
class BlockTpl
{
public:
BlockTpl():_nx(nx),_ny(ny){}
void Report(void)
{
cout << "BlockTpl With Size ["<<_nx<<","<<_ny<<"]\n";
}
private:
const int _nx;
const int _ny;
double _data[nx][ny]; // uncomfortable here, can't use _nx, _ny
};
int main(int argc, const char *argv[])
{
Block b(3,3);
b.Report();
BlockAuto ba(3,3);
ba.Report();
BlockTpl<3,4> bt;
bt.Report();
return 0;
}
Just use a std::vector. I had the same decision problem a week before and had asked here.
If you use reserve(), which shall not make your vector reallocate itself many times(if any), then vectors are not going to influence the performance of your project. In other words, vector is unlikely to be your bottleneck.
Notice, that in C++ vectors are used widely, thus in release mode, the optimizations made to them are really efficient.
Or wait for std::dynarray to be introduced! (Unfortunately not in C++14, but in array TS or C++17). Source, credits to manlio.
Never forget: Premature optimization is the source of Evil. - Knuth.
Don't believe me? You shouldn't! Experiment yourself and find out!
Here is my experiment to get me convinced when I had exactly the same question as you.
Experiment code:
#include <iostream>
#include <vector>
#include <ctime>
#include <ratio>
#include <chrono>
using namespace std;
int main() {
const int N = 100000;
cout << "Creating, filling and accessing an array of " << N << " elements.\n";
using namespace std::chrono;
high_resolution_clock::time_point t1 = high_resolution_clock::now();
int array[N];
for(int i = 0; i < N; ++i)
array[i] = i;
for(int i = 0; i < N; ++i)
array[i] += 5;
high_resolution_clock::time_point t2 = high_resolution_clock::now();
duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
std::cout << "It took me " << time_span.count() << " seconds.";
std::cout << std::endl;
cout << "Creating, filling and accessing an vector of " << N << " elements.\n";
t1 = high_resolution_clock::now();
vector<int> v;
v.reserve(N);
for(int i = 0; i < N; ++i)
v.emplace_back(i);
for(int i = 0; i < N; ++i)
v[i] += 5;
t2 = high_resolution_clock::now();
time_span = duration_cast<duration<double>>(t2 - t1);
std::cout << "It took me " << time_span.count() << " seconds.";
std::cout << std::endl;
return 0;
}
Results (notice the -o2 compiler flag):
samaras#samaras-A15:~$ g++ -std=gnu++0x -o2 px.cpp
samaras#samaras-A15:~$ ./a.out
Creating, filling and accessing an array of 100000 elements.
It took me 0.002978 seconds.
Creating, filling and accessing an vector of 100000 elements.
It took me 0.002264 seconds.
So, just a std::vector. :) I am pretty sure you know how to change your code for that and you do not need me to tell you (is so, let me know of course :) ).
You can try with other time methods, found in my pseudo-site.
I think you're being overly cautious in rejecting std::vector just because of the resizability issue. Surely your program can accommodate sizeof(Block) being a few of pointer sizes larger than the raw pointer solution. A vector for maintaining the matrix should be no different than your pointer solution as far as performance goes, if you use a single vector instead of a vector of vectors.
Using vector will also make it a lot more unlikely that you'll screw up. For instance, your auto_ptr solution has undefined behavior because the auto_ptr is going to delete, instead of delete[], the array in the destructor. Also, you most likely won't get the behavior you expect unless you define a copy constructor and assignment operator.
Now, if you must eschew vector, I'd suggest using unique_ptr instead of auto_ptr.
class Block
{
public:
Block(int nx, int ny):_nx(nx),_ny(ny), _data(new double[_nx*_ny])
{}
void Report(void)
{
cout << "Block With Size ["<<_nx<<","<<_ny<<"]\n";
}
private:
const int _nx, _ny;
std::unique_ptr<double[]> _data; // here
};
This will correctly call delete[] and it won't transfer ownership of the array as readily as auto_ptr.
std::vector is your friend, no need to rebuild the wheel :
class Block
{
public:
BlockAuto(int p_rows, int p_cols):m_rows(nx),m_cols(ny)
{
m_vector.resize(m_rows*m_cols);
}
double at(uint p_x, uint p_y)
{
//Some check that p_x and p_y aren't over limit is advised
return m_vector[p_x + p_y*m_rows];
}
void Report(void)
{
cout << "Block With Size ["<<_nx<<","<<_ny<<"]\n";
}
private:
const int m_rows;
const int m_cols;
std::vector<double> m_vector;
//or double* m_data
};
You may also use a simple double* as in your first solution. Do not forget to delete it when destroying the block though.
Memory is cheap these days, and your block matrices are very very small.
So, when you don't want to use templates, and don't want to use dynamic allocation, well just use a fixed size array sufficiently large for the largest possible block.
It's that simple.
The code you show with std::auto_ptr has two main problems:
std::auto_ptr is deprecated in C++11.
std::auto_ptr always performed a delete p, which yields Undefined Behavior when the allocation was of an array, like new T[n].
By the way, regarding the envisioned code bloat with templates, you may be pleasantly surprised if you measure.
Also in passing, this smells quite a bit of premature optimization. With C++ it's a good idea to always keep performance in mind, and not do needlessly slow or memory consuming things. But also, a good idea to not get bogged down in needlessly working around some perceived performance problem that really doesn't matter, or wouldn't have mattered if it were just ignored.
And so, your main default choice should be to use a std::vector for the storage.
Then, if you suspect that it's too slow, measure. The release version. Oh I've said that only twice, so here's third: measure. ;-)

Compare two static arrays

I have an issue how to implement to compare two static arrays, ie.
string bufferNames[]={"apple","orange","banana","pomegranate","pear"};
string bufferPictures[] = {"apple.bmp","orange.bmp","banana.bmp","pomegranate.bmp","pear.bmp"};
Each item in the bufferNames presents the choice that to someone has been given, when the picture from the bufferPictures has been loaded onto the screen. So, if I for example get orange.bmp using rand() function that iterates through that list, how can I get the same one corresponding element orange and two other random not correct elements. Any help would be appreciated.
Thanks in advance.
P.S. If further breaking in of the problem is needed, just say it so.
This should do it. The code makes use of the C++11 features. You will
need to adapt it, to pass it off as homework.
#include <string>
#include <iostream>
#include <algorithm>
#include <vector>
struct Picture {
std::string name, file;
bool operator==(const Picture& x) const { return this->name == x.name && this->file == x.file; }
bool operator!=(const Picture& x) const { return !(*this == x); }
};
int main()
{
std::vector< Picture > pics =
{
{"apple", "apple.bmp"},
{"orange", "orange.bmp"},
{"banana", "banana.bmp"},
{"pear", "pear.bmp"},
};
// determined by random choice
const Picture& choice = pics[0];
std::vector< Picture > woChoice;
std::copy_if(pics.begin(), pics.end(), std::back_inserter(woChoice),
[&choice](const Picture& x) {
return x != choice;
});
// random shuffle the remainder and pick the first
// two. alternatively and for more efficience use std::random to
// generate indices
std::random_shuffle(woChoice.begin(), woChoice.end());
std::cout << woChoice[0].name << std::endl;
std::cout << woChoice[1].name << std::endl;
return 0;
}
So, if I for example get orange.bmp using rand() function that iterates through that list, how can I get the same one corresponding element orange and two other random not correct elements.
If you use rand() to get a number (let's call it x) between 0 and 4 inclusive (based on there being 5 distinct values in the arrays), then you can use that number in both arrays to find the related word and image.
To get one other random incorrect element, you can call rand() in a loop until you get a value other than x. Let's call it y.
To get another random incorrect elements, you can call rand() in a loop until you get a value other than x and y.
There are other ways to do this, but that's probably easiest to understand and implement.
The names in arrays correspond to each other. So, if you need fruit
number i, take bufferNames[i] and bufferPictures[i] in parallel way.
Ensure that names ARE parallel. Simply making the second array
elements from the first array elements.
As for random in range 0..n-1 excluding elements number i,j (j>i), count it so:
temp=random(n-3);
k=(temp>=i?temp+1:temp);
k=(k>=j?k+1:k);
And again, take bufferNames[k] and bufferPictures[k].
It is not simple, it is VERY simple.

Understanding boost::disjoint_sets

I need to use boost::disjoint_sets, but the documentation is unclear to me. Can someone please explain what each template parameter means, and perhaps give a small example code for creating a disjoint_sets?
As per the request, I am using disjoint_sets to implement Tarjan's off-line least common ancestors algorithm, i.e - the value type should be vertex_descriptor.
What I can understand from the documentation :
Disjoint need to associate a rank and a parent (in the forest tree) to each element. Since you might want to work with any kind of data you may,for example, not always want to use a map for the parent: with integer an array is sufficient. You also need a rank foe each element (the rank needed for the union-find).
You'll need two "properties" :
one to associate an integer to each element (first template argument), the rank
one to associate an element to an other one (second template argument), the fathers
On an example :
std::vector<int> rank (100);
std::vector<int> parent (100);
boost::disjoint_sets<int*,int*> ds(&rank[0], &parent[0]);
Arrays are used &rank[0], &parent[0] to the type in the template is int*
For a more complex example (using maps) you can look at Ugo's answer.
You are just giving to the algorithm two structures to store the data (rank/parent) he needs.
disjoint_sets<Rank, Parent, FindCompress>
Rank PropertyMap used to store the size of a set (element -> std::size_t). See union by rank
Parent PropertyMap used to store the parent of an element (element -> element). See Path compression
FindCompress Optional argument defining the find method. Default to find_with_full_path_compression See here (Default should be what you need).
Example:
template <typename Rank, typename Parent>
void algo(Rank& r, Parent& p, std::vector<Element>& elements)
{
boost::disjoint_sets<Rank,Parent> dsets(r, p);
for (std::vector<Element>::iterator e = elements.begin();
e != elements.end(); e++)
dsets.make_set(*e);
...
}
int main()
{
std::vector<Element> elements;
elements.push_back(Element(...));
...
typedef std::map<Element,std::size_t> rank_t; // => order on Element
typedef std::map<Element,Element> parent_t;
rank_t rank_map;
parent_t parent_map;
boost::associative_property_map<rank_t> rank_pmap(rank_map);
boost::associative_property_map<parent_t> parent_pmap(parent_map);
algo(rank_pmap, parent_pmap, elements);
}
Note that "The Boost Property Map Library contains a few adaptors that convert commonly used data-structures that implement a mapping operation, such as builtin arrays (pointers), iterators, and std::map, to have the property map interface"
This list of these adaptors (like boost::associative_property_map) can be found here.
For those of you who can't afford the overhead of std::map (or can't use it because you don't have default constructor in your class), but whose data is not as simple as int, I wrote a guide to a solution using std::vector, which is kind of optimal when you know the total number of elements beforehand.
The guide includes a fully-working sample code that you can download and test on your own.
The solution mentioned there assumes you have control of the class' code so that in particular you can add some attributes. If this is still not possible, you can always add a wrapper around it:
class Wrapper {
UntouchableClass const& mInstance;
size_t dsID;
size_t dsRank;
size_t dsParent;
}
Moreover, if you know the number of elements to be small, there's no need for size_t, in which case you can add some template for the UnsignedInt type and decide in runtime to instantiate it with uint8_t, uint16_t, uint32_tor uint64_t, which you can obtain with <cstdint> in C++11 or with boost::cstdint otherwise.
template <typename UnsignedInt>
class Wrapper {
UntouchableClass const& mInstance;
UnsignedInt dsID;
UnsignedInt dsRank;
UnsignedInt dsParent;
}
Here's the link again in case you missed it: http://janoma.cl/post/using-disjoint-sets-with-a-vector/
I written a simple implementation a while ago. Have a look.
struct DisjointSet {
vector<int> parent;
vector<int> size;
DisjointSet(int maxSize) {
parent.resize(maxSize);
size.resize(maxSize);
for (int i = 0; i < maxSize; i++) {
parent[i] = i;
size[i] = 1;
}
}
int find_set(int v) {
if (v == parent[v])
return v;
return parent[v] = find_set(parent[v]);
}
void union_set(int a, int b) {
a = find_set(a);
b = find_set(b);
if (a != b) {
if (size[a] < size[b])
swap(a, b);
parent[b] = a;
size[a] += size[b];
}
}
};
And the usage goes like this. It's simple. Isn't it?
void solve() {
int n;
cin >> n;
DisjointSet S(n); // Initializing with maximum Size
S.union_set(1, 2);
S.union_set(3, 7);
int parent = S.find_set(1); // root of 1
}
Loic's answer looks good to me, but I needed to initialize the parent so that each element had itself as parent, so I used the iota function to generate an increasing sequence starting from 0.
Using Boost, and I imported bits/stdc++.h and used using namespace std for simplicity.
#include <bits/stdc++.h>
#include <boost/pending/disjoint_sets.hpp>
#include <boost/unordered/unordered_set.hpp>
using namespace std;
int main() {
array<int, 100> rank;
array<int, 100> parent;
iota(parent.begin(), parent.end(), 0);
boost::disjoint_sets<int*, int*> ds(rank.begin(), parent.begin());
ds.union_set(1, 2);
ds.union_set(1, 3);
ds.union_set(1, 4);
cout << ds.find_set(1) << endl; // 1 or 2 or 3 or 4
cout << ds.find_set(2) << endl; // 1 or 2 or 3 or 4
cout << ds.find_set(3) << endl; // 1 or 2 or 3 or 4
cout << ds.find_set(4) << endl; // 1 or 2 or 3 or 4
cout << ds.find_set(5) << endl; // 5
cout << ds.find_set(6) << endl; // 6
}
I changed std::vector to std::array because pushing elements to a vector will make it realloc its data, which makes the references the disjoint sets object contains become invalid.
As far as I know, it's not guaranteed that the parent will be a specific number, so that's why I wrote 1 or 2 or 3 or 4 (it can be any of these). Maybe the documentation explains with more detail which number will be chosen as leader of the set (I haven't studied it).
In my case, the output is:
2
2
2
2
5
6
Seems simple, it can probably be improved to make it more robust (somehow).
Note: std::iota Fills the range [first, last) with sequentially increasing values, starting with value and repetitively evaluating ++value.
More: https://en.cppreference.com/w/cpp/algorithm/iota

A proper way to create a matrix in c++

I want to create an adjacency matrix for a graph. Since I read it is not safe to use arrays of the form matrix[x][y] because they don't check for range, I decided to use the vector template class of the stl. All I need to store in the matrix are boolean values. So my question is, if using std::vector<std::vector<bool>* >* produces too much overhead or if there is a more simple way for a matrix and how I can properly initialize it.
EDIT: Thanks a lot for the quick answers. I just realized, that of course I don't need any pointers. The size of the matrix will be initialized right in the beginning and won't change until the end of the program. It is for a school project, so it would be good if I write "nice" code, although technically performance isn't too important. Using the STL is fine. Using something like boost, is probably not appreciated.
Note that also you can use boost.ublas for matrix creation and manipulation and also boost.graph to represent and manipulate graphs in a number of ways, as well as using algorithms on them, etc.
Edit: Anyway, doing a range-check version of a vector for your purposes is not a hard thing:
template <typename T>
class BoundsMatrix
{
std::vector<T> inner_;
unsigned int dimx_, dimy_;
public:
BoundsMatrix (unsigned int dimx, unsigned int dimy)
: dimx_ (dimx), dimy_ (dimy)
{
inner_.resize (dimx_*dimy_);
}
T& operator()(unsigned int x, unsigned int y)
{
if (x >= dimx_ || y>= dimy_)
throw std::out_of_range("matrix indices out of range"); // ouch
return inner_[dimx_*y + x];
}
};
Note that you would also need to add the const version of the operators, and/or iterators, and the strange use of exceptions, but you get the idea.
Best way:
Make your own matrix class, that way you control every last aspect of it, including range checking.
eg. If you like the "[x][y]" notation, do this:
class my_matrix {
std::vector<std::vector<bool> >m;
public:
my_matrix(unsigned int x, unsigned int y) {
m.resize(x, std::vector<bool>(y,false));
}
class matrix_row {
std::vector<bool>& row;
public:
matrix_row(std::vector<bool>& r) : row(r) {
}
bool& operator[](unsigned int y) {
return row.at(y);
}
};
matrix_row& operator[](unsigned int x) {
return matrix_row(m.at(x));
}
};
// Example usage
my_matrix mm(100,100);
mm[10][10] = true;
nb. If you program like this then C++ is just as safe as all those other "safe" languages.
The standard vector does NOT do range checking by default.
i.e. The operator[] does not do a range check.
The method at() is similar to [] but does do a range check.
It will throw an exception on out of range.
std::vector::at()
std::vector::operator[]()
Other notes:
Why a vector<Pointers> ?
You can quite easily have a vector<Object>. Now there is no need to worry about memory management (i.e. leaks).
std::vector<std::vector<bool> > m;
Note: vector<bool> is overloaded and not very efficient (i.e. this structure was optimized for size not speed) (It is something that is now recognized as probably a mistake by the standards committee).
If you know the size of the matrix at compile time you could use std::bitset?
std::vector<std::bitset<5> > m;
or if it is runtime defined use boost::dynamic_bitset
std::vector<boost::dynamic_bitset> m;
All of the above will allow you to do:
m[6][3] = true;
If you want 'C' array performance, but with added safety and STL-like semantics (iterators, begin() & end() etc), use boost::array.
Basically it's a templated wrapper for 'C'-arrays with some NDEBUG-disable-able range checking asserts (and also some std::range_error exception-throwing accessors).
I use stuff like
boost::array<boost::array<float,4>,4> m;
instead of
float m[4][4];
all the time and it works great (with appropriate typedefs to keep the verbosity down, anyway).
UPDATE: Following some discussion in the comments here of the relative performance of boost::array vs boost::multi_array, I'd point out that this code, compiled with g++ -O3 -DNDEBUG on Debian/Lenny amd64 on a Q9450 with 1333MHz DDR3 RAM takes 3.3s for boost::multi_array vs 0.6s for boost::array.
#include <iostream>
#include <time.h>
#include "boost/array.hpp"
#include "boost/multi_array.hpp"
using namespace boost;
enum {N=1024};
typedef multi_array<char,3> M;
typedef array<array<array<char,N>,N>,N> C;
// Forward declare to avoid being optimised away
static void clear(M& m);
static void clear(C& c);
int main(int,char**)
{
const clock_t t0=clock();
{
M m(extents[N][N][N]);
clear(m);
}
const clock_t t1=clock();
{
std::auto_ptr<C> c(new C);
clear(*c);
}
const clock_t t2=clock();
std::cout
<< "multi_array: " << (t1-t0)/static_cast<float>(CLOCKS_PER_SEC) << "s\n"
<< "array : " << (t2-t1)/static_cast<float>(CLOCKS_PER_SEC) << "s\n";
return 0;
}
void clear(M& m)
{
for (M::index i=0;i<N;i++)
for (M::index j=0;j<N;j++)
for (M::index k=0;k<N;k++)
m[i][j][k]=1;
}
void clear(C& c)
{
for (int i=0;i<N;i++)
for (int j=0;j<N;j++)
for (int k=0;k<N;k++)
c[i][j][k]=1;
}
What I would do is create my own class for dealing with matrices (probably as an array[x*y] because I'm more used to C (and I'd have my own bounds checking), but you could use vectors or any other sub-structure in that class).
Get your stuff functional first then worry about how fast it runs. If you design the class properly, you can pull out your array[x*y] implementation and replace it with vectors or bitmasks or whatever you want without changing the rest of the code.
I'm not totally sure, but I thing that's what classes were meant for, the ability to abstract the implementation well out of sight and provide only the interface :-)
In addition to all the answers that have been posted so far, you might do well to check out the C++ FAQ Lite. Questions 13.10 - 13.12 and 16.16 - 16.19 cover several topics related to rolling your own matrix class. You'll see a couple of different ways to store the data and suggestions on how to best write the subscript operators.
Also, if your graph is sufficiently sparse, you may not need a matrix at all. You could use std::multimap to map each vertex to those it connects.
my favourite way to store a graph is vector<set<int>>; n elements in vector (nodes 0..n-1), >=0 elements in each set (edges). Just do not forget adding a reverse copy of every bi-directional edge.
Consider also how big is your graph/matrix, does performance matter a lot? Is the graph static, or can it grow over time, e.g. by adding new edges?
Probably, not relevant as this is an old question, but you can use the Armadillo library, which provides many linear algebra oriented data types and functions.
Below is an example for your specific problem:
// In C++11
Mat<bool> matrix = {
{ true, true},
{ false, false},
};
// In C++98
Mat<bool> matrix;
matrix << true << true << endr
<< false << false << endr;
Mind you std::vector doesn't do range checking either.