C++: Values of both objects changes after a Copy Constructor - c++

I have written a simple c++ code to understand the concepts of Copy Constructor/Operator Overloading. A snippet of the code is shown below.
In the code I am creating an object vec v2 and then creating a new object v4 and assign vec v2. Next I called the overloaded operator[] to change the values of v4[0] and v4[1].
My issue is that after assigning these values, the values of vec v2 has also changed.
I am not quite sure how this could have happened. Hope anyone can help me with this.
class vec {
private:
// Variable to store the number of elements contained in this vec.
size_t elements;
// Pointer to store the address of the dynamically allocated memory.
double* data;
public:
vec(size_t size) : elements{ size }, data{ new double[size] } {std::cout << "First constructor" << "\n"; };
vec(size_t size, double ival) : elements{ size }, data{ new double[size] } {
std::cout << "Second constructor" << std::endl;
for (int i = 0; i < elements; i++) {
data[i] = ival;
}
}
vec(std::initializer_list<double> iList): vec(static_cast<size_t>(iList.size())) {
std::cout << "Third constructor" << std::endl;
auto count{ 0 };
for (auto element: iList) {
data[count] = element;
count++;
}
}
/// Copy constructor that creates a copy of the vec variable 'v'.
vec(const vec& v) : elements{ v.elements }, data{ new double[v.elements] }{
std::cout << "Copy constructor " << "\n";
std::memcpy(&data, &(v.data), v.elements);
}
/// Copy assignment operator. Creates a copy of vec variable 'v'.
vec& operator=(const vec& v) {
std::cout << "Copy assignment " << "\n";
if (this != &v) {
const auto new_data{ new double[v.elements] };
delete[] data;
data = new_data;
elements = v.elements;
std::memcpy(&data, &(v.data), v.elements);
}
return *this;
}
double& operator[](size_t idx){
return this->data[idx];
}
friend std::ostream& operator<<(std::ostream& os, const vec& v) {
for (int i = 0; i < v.elements; i++) {
os << v.data[i] << "\n";
}
return os;
}
};
int main(void) {
vec v2 = {4, 5, 6};
vec v4 = v2
v4[0] = 11; // call to operator[]
v4[1] = 12; // call to operator[]
return 0;
}

The issue is the misuse of the std::memcpy function:
std::memcpy(&data, &(v.data), v.elements);
Since data and v.data are already pointers to the data, getting the address of those pointers results in the incorrect pointer values being used for those arguments.
The other issue is that the third argument v.elements should denote the number of bytes, not the number of elements, to copy.
The correct call to std::memcpy should have been:
std::memcpy(data, v.data, v.elements * sizeof(double));
But having said all this, do not use std::memcpy, and instead use std::copy. That will work with the number of elements, plus can work with types that are not trivially-copyable (such as std::string):
#include <algorithm>
//...
std::copy(v.data, v.data + v.elements, data);

Related

C++: Disassemble a flat vector into multiple vectors of equal size without copying

Is it possible in C++ to split a flat vector (or C style array) into multiple vectors of equal size without copying any of its containing data? That is, disassembling the original vector by moving its content to a new vector, which invalidates the original vector. The following code example should illustrate this:
#include <cassert>
#include <vector>
void f(int* v) {
for (int i = 0; i < 100; i++) {
v[i] = i;
}
}
/**
* Split v into n vectors of equal size without copy its data (assert v.size() % n == 0)
*/
std::vector<std::vector<int>> g(std::vector<int> v, int n) {
std::vector<std::vector<int>> vs(n);
int vec_size = v.size() / n;
for (int i = 0; i < n; i++) {
vs[i].assign(v.begin() + i * vec_size, v.begin() + (i + 1) * vec_size); // copies?
// how to let vs[i] point to v.begin() + i * vec_size?
}
return vs;
}
int main() {
std::vector<int> v(100);
f(v.data());
std::vector<std::vector<int>> vs = g(std::move(v), 10);
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
assert(vs[i][j] == i * 10 + j);
}
}
return 0;
}
Yes, in my opinion this is possible. Moving the elements, but not copying the elements.
C++ offers std::make_move_iterator. Please read here about that.
To check that, I created a small class to output, to see, if we copy or move something.
So, if your data can "move", then it will work, otherwise of course a copy will be made. With the following we see the result.
struct Test {
int data{};
Test(int d) : data(d) { std::cout << "Construct and init\n"; }
Test() { std::cout << "Default construct\n"; };
~Test() { std::cout << "Destruct\n"; };
Test(const Test& other) { std::cout << "Construct\n"; data = other.data; }
Test(const Test&& other) noexcept { std::cout << "Move Construct\n"; data = other.data; }
Test& operator =(const Test& other) noexcept { std::cout << "Assign\n"; data = other.data; return *this; }
Test& operator =(const Test&& other) noexcept { std::cout << "Move Assign\n"; data = other.data; return *this; }
};
We will additionally add a small function, which calculates the offsets of the chunks that will be moved.
And then, we can come up with a small function to implement that.
#include <iostream>
#include <vector>
#include <numeric>
#include <iterator>
#include <iomanip>
// Calculate start and end index for all chunks
std::vector<std::pair<size_t, size_t>> calculatePairs(const size_t low, const size_t high, const size_t numberOfGroups) {
// Here we will store the resulting pairs with start and end values
std::vector<std::pair<size_t, size_t>> pairs{};
// Calculate chung size and remainder
const size_t delta = high - low;
const size_t chunk = delta / numberOfGroups;
size_t remainder = delta % numberOfGroups;
// Calculate the chunks start and end addresses for all chunks
size_t startIndex{}, endIndex{};
for (size_t i = 0; i < numberOfGroups; ++i) {
// Calculate end address and distribute remainder equally
endIndex = startIndex + chunk + (remainder ? 1 : 0);
// Store a new pair of start and end indices
pairs.emplace_back(startIndex, endIndex);
// Next start index
startIndex = endIndex;
// We now consumed 1 remainder
if (remainder) --remainder;
}
//--pairs.back().second;
return pairs;
}
struct Test {
int data{};
Test(int d) : data(d) { std::cout << "Construct and init\n"; }
Test() { std::cout << "Default construct\n"; };
~Test() { std::cout << "Destruct\n"; };
Test(const Test& other) { std::cout << "Construct\n"; data = other.data; }
Test(const Test&& other) noexcept { std::cout << "Move Construct\n"; data = other.data; }
Test& operator =(const Test& other) noexcept { std::cout << "Assign\n"; data = other.data; return *this; }
Test& operator =(const Test&& other) noexcept { std::cout << "Move Assign\n"; data = other.data; return *this; }
};
std::vector<std::vector<Test>> split(std::vector<Test>& v, unsigned int n) {
std::vector<std::vector<Test>> result{};
if (v.size() > n) {
result.resize(n);
std::vector<std::pair<size_t, size_t>> offset = calculatePairs(0u, v.size(), n);
for (size_t i{}; i < n; ++i) {
result[i].insert(result[i].end(), std::make_move_iterator(v.begin() + offset[i].first),
std::make_move_iterator(v.begin() + offset[i].second));
}
}
return result;
}
constexpr size_t NumberOfElements = 30u;
constexpr unsigned int NumberOfGroups = 3;
static_assert (NumberOfElements >= NumberOfGroups, "Number of elements must be greater/equal then number of elements\n");
int main() {
std::cout << "\n\n\nCreate vector with " << NumberOfElements << " elements\n\n";
std::vector<Test> v1(NumberOfElements);
std::cout << "\n\n\nFill vector with std::iota\n\n";
std::iota(v1.begin(), v1.end(), 1);
std::cout << "\n\n\nSplit in " << NumberOfGroups<< "\n\n";
std::vector<std::vector<Test>> s = split(v1, NumberOfGroups);
std::cout << "\n\n\nOutput\n\n";
for (const std::vector<Test>& vt : s) {
for (const Test& d : vt) std::cout << std::setw(3) << d.data << ' ';
std::cout << "\n\n";
}
}
But my strong guess is that you want to splice the data. The underlying elements fo the std::vector which you can get with the data() function.
You can access the data easily with pointer arithmetic on data().
But if you want to have the data in a new container, then this is difficult with a std::vector. It can for example be done with a std::list that has a splice function and does, what you want.
Or, you need to implement your own dynamic array and implement a splice function . . .
Checksum:
;23M#eTo1?:B#r7C8#wtJ'Z'..uIvLT.j;bld$Bvgjd.qm=8;B/`dHM%D#wyv:\5YI:WVGwJL00%IsKQ9O+&#g,/gzkPg^cg::LX?6dL3;Fs3GOOAmQmCIW?&skWxZXsElyn6S3#fi:0DSKJ/A^r#*'k#a#e8!XDpjAUtu?K5iu+e=P"M7a2BWdFdA.5NP:Y"l,,h+Y/PxhVfP/m0ceS=Nxol2vOZwM2+!H\^a=douX%fhqcr4'0eXiEZeKvTf0^%CTNY^WB6fc#IpK^GQgxTXQo0ikr0+/OxXlc1B$5jc1r,GQj+fwEdoCPrz6,j:SO6L3QU#7lT:f#Y^V!Au\P'a5amR$NCU?\WspBOuy#RH3tJimka#rdyNN56.$;DtRCHN*YeWlrG=',XNSrzEK:Cw;#A%.#/:c,a2W24IIIdecc7O"EnKQn;nXmUemX4kclDsYci+izmr#vlGAQ.w2!cuf;6n2UvJM,CeSyRj1,:2\9#i8GLwtux!uEHUp7X*5SC%nld956CHsy&/n73/90cRP'Me"1PW+##FH8mH4Rf^o=ZP/Rm\X&1syUdUh+.N/jtoO:,OBBAmq,jW69Fu%jJukBa$g4hIrIPcxx17i;XU,FCbQGd8v*AyKGSML\JN#jte*F";Zh7fqhvCXobE&SapX90r"Z$.CN,1R^aj.=5L6^tUB2UPJH^eb'*B!v5=D.9PFI#Pt*KjK+yS*tV6f.5kgPOzBE$uK0MA/\l9U"63LUR6k3#'cub?u&xILMXP%#:lx2TbKhFOjBpMN!+%F16jrgv&AoFhuf%P!==8?x,NsSd%hVo"BJhVv3rjrhvM"WLE3%y#N7g37Re^XiS9lpyKA9E7ow6U=I"tlv",&#+fZoIR4KM58!NTm978wCI?9wo.ocS!9i5k#ler47J.G0yXjZVSdr=G"uRodC06k\V%8;oUwV&z!W5:+ZvE:nyO#+lO+Hn0&tnH&^tNC?'PmERxs/B+KW4O6&oWDED9?MqxmYgVKoT.a%iw

C++ "const std::any &" more copy constructor call than without std::any

#include <iostream>
#include <vector>
#include <string>
#include <any>
using namespace std;
template <typename T>
class MyVector {
private:
int n;
T* data;
public:
MyVector() {
n = 0;
data = nullptr;
cout << "MyVector default constructor\n";
}
MyVector(int _n) {
n = _n;
data = new T[n];
cout << "MyVector param constructor\n";
}
MyVector(const MyVector& other) {
n = other.n;
data = new T[n];
for (int i=0; i<n; i++) data[i] = other.data[i];
cout << "MyVector copy constructor\n";
}
MyVector(MyVector&& other) {
n = other.n;
data = other.data;
other.n = 0;
other.data = nullptr;
cout << "MyVector move constructor\n";
}
MyVector& operator = (const MyVector& other) {
if (this != &other) {
n = other.n;
delete[] data;
data = new T[n];
for (int i=0; i<n; i++) data[i] = other.data[i];
}
cout << "MyVector copy assigment\n";
return *this;
}
MyVector& operator = (MyVector&& other) {
if (this != &other) {
n = other.n;
delete[] data;
data = other.data;
other.n = 0;
other.data = nullptr;
}
cout << "MyVector move assigment\n";
return *this;
}
~MyVector() {
delete[] data;
cout << "MyVector destructor: size = " << n << "\n";
}
int size() {
return n;
}
};
template <typename T>
any func_any(const any &vec) {
cout << "\nBefore func_any assignment\n";
MyVector<T> res = any_cast<MyVector<T>>(vec); // I want res to const reference MyVector<T> vec, not copy
cout << "\nAfter func_any assignment\n";
return res;
}
template <typename T>
MyVector<T> func(const MyVector<T> &vec) {
cout << "\nBefore func assignment\n";
MyVector<T> res = vec;
cout << "\nAfter func assignment\n";
return res;
}
int main()
{
MyVector<int> a(5);
MyVector<int> a2(6);
cout << "-----------";
cout << "\nBefore func_any call\n";
auto b = func_any<int>(a);
cout << "\nAfter func_any call\n";
cout << "--------------";
cout << "\nBefore func call\n";
auto c = func<int>(a2);
cout << "\nAfter func call\n";
cout << "-----------------";
cout << "\nBefore exit\n";
return 0;
}
I am trying to make a function-executor base class with Python like interface (use std::any as input and output). In each child class, the actual type input type is known at compile time, so I wish to cast std::any to a specific type. In the example above I just use a function to make it simple.
However, the function with std::any call constructors and destructors many times more than the function without. The above program give the following input:
MyVector param constructor
MyVector param constructor
-----------
Before func_any call
MyVector copy constructor
Before func_any assignment
MyVector copy constructor
After func_any assignment
MyVector move constructor
MyVector destructor: size = 0
MyVector destructor: size = 5
After func_any call
--------------
Before func call
Before func assignment
MyVector copy constructor
After func assignment
After func call
-----------------
Before exit
MyVector destructor: size = 6
MyVector destructor: size = 5
MyVector destructor: size = 6
MyVector destructor: size = 5
So the function version that uses std::any needs 3 constructor + 2 destructor calls. While the normal version needs just 1 constructor call. I assume the return statement in func is copy elision.
How can I improve this? The most important thing I need is below, if it's impossible with std::any then please provide a possible solution with std::variant.
MyVector<T> res = any_cast<MyVector<T>>(vec); // I want res to const reference MyVector<T> vec, not copy
An object needs to be copied into the std::any, so trying to call func_any<int>(a) will copy a.
You can instead hold a std::reference_wrapper<T> or a T* pointer in the std::any:
template <typename T>
any func_any(const any &vec) {
cout << "\nBefore func_any assignment\n";
MyVector<T> res = any_cast<std::reference_wrapper<const MyVector<T>>>(vec);
cout << "\nAfter func_any assignment\n";
return res;
}
auto b = func_any<int>(std::cref(a));
Since you already know what types are actually being used, you might be better off making your base class use void* as input and output.
You can also any_cast to a reference type:
const MyVector<T>& res = std::any_cast<const MyVector<T>&>(vec)
This will be a reference to the value held in vec (so no constructors involved). This will not reduce the overall number of copies, but it will get rid of one move due to NRVO.

Memory overwrite in my own Vector class

For my Algorithm course project we can't use STL stuff like std::vector and so I'm trying to implement my own version of it (with templates).
It seems it works but when I declare a Vector< Vector< int > >
the .push() method starts to overwrite memory.
More specifically, with this code:
Vector<Vector<int>> v(3);
cout << v[0].push(0) << "\n";
cout << v[0].push(55) << "\n";
cout << v[0].push(4) << "\n";
cout << v[1].push(12) << "\n";
cout << v[1].push(3) << "\n";
cout << v[2].push(1) << "\n";
The output is this (.push() returns the address of where the element is inserted):
0x561328b0bc20
0x561328b0bc24
0x561328b0bc28
0x561328b0bc20
0x561328b0bc24
0x561328b0bc20
Any suggestion of why this happens?
Here is the code for my Vector class:
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
template<class T>
class Vector {
private:
size_t _size;
size_t _capacity;
char* _buffer; //char* for performance
void _realloc(size_t);
public:
Vector(size_t s=0, T def=T());
T* push(T);
T& operator[](int);
size_t size() { return _size; }
};
template<class T>
void Vector<T>:: _realloc(size_t ncap)
{
_capacity = ncap;
char* nbuf = _buffer;
_buffer = new char[_capacity];
for(size_t i=0; i<_size * sizeof(T); ++i)
_buffer[i] = nbuf[i];
delete[] nbuf;
}
/*
* s -> size
* def -> default value
*/
template<class T>
Vector<T>:: Vector(size_t s, T def) : _size(s)
{
_capacity = 32;
while(_capacity < _size)
_capacity *= 2;
_buffer = new char[_capacity * sizeof(T)];
for(size_t i=0; i<_size; ++i)
((T*)_buffer)[i] = def;
}
/*
* check capacity, reallocs if necessary and push the element
* then return the addres (used only for debug)
*/
template<class T>
T* Vector<T>:: push(T ele)
{
if(_capacity == _size)
_realloc(2 * _capacity);
((T*)_buffer)[_size++] = ele;
return &((T*)_buffer)[_size-1];
}
template<class T>
T& Vector<T>:: operator[](int i)
{
if(i<0 or i>=(int)_size) {
cerr << "Out of bounds!\n";
abort();
}else
return ((T*)_buffer)[i];
}
template<class T>
ostream& operator<<(ostream& out, Vector<T>& v)
{
out << "{";
if(v.size() > 0) {
out << v[0];
for(size_t i=1; i<v.size(); ++i)
out << ", " << v[i];
}
out << "}";
return out;
}
Thanks!
PS: I know it's not a good use of C++ :P
Your operator= implicitly defined does the wrong thing. You use it in your constructor.
So, follow the rule of 0/3/5: Implement copy/move construtors/assignment and destructors, as this is an owning memory-management type. (Non-resource management types should follow the rule of 0; copyable resource management types the rule of 5.)
See rule of three. Implement all of destructor/copy constructor/move constructor/copy assign/move assign, or none of them.
Don't copy the data byte-wise when you realloc. std::move the Ts from the source to the dest.
In the copy construct/assign you'll want to copy the source Ts, not the underlying bytes.

array of vector<struct> in C++

I've a vector of structure and it's components, now I want array of this group, below is my code
struct V1
{
USHORT val;
UINT cnt;
USHORT state;
};
struct V2
{
DWORD room;
vector <V1> vref;
bool update_V1(USHORT S1, USHORT S2);
VOID ClearState(USHORT S1);
};
struct V3
{
USHORT block;
vector <V2> V2ref;
bool Update_V2(DWORD S1,USHORT S2,USHORT S3);
VOID ClearState_V2(USHORT S4);
};
struct V4
{
USHORT space;
vector <V3> V3ref;
bool Update_V3(USHORT S1,DWORD S2,USHORT S3);
VOID ClearState_V2(USHORT S4);
};
struct V5
{
USHORT del_1;
vector <V4> V4ref;
bool Update_V4(USHORT S1,USHORT S2,DWORD S3,USHORT S4);
VOID ClearState_V2(USHORT S4);
};
class C1
{
vector<V5> V5ref[2];
bool UpdateGroup(USHORT S1,USHORT S2,USHORT S3,DWORD S4,USHORT S5);
}
bool C1::UpdateGroup(USHORT S1,USHORT S2,USHORT S3,DWORD S4,USHORT S5)
{
vector<V5>::iterator it;
for ( it=V5ref[S5].begin() ; it< V5ref[S5].end(); it++ )
{
if(it->del_1==S2)
{
return grpItr->Update_V4(S1,S2,S3,s4);
}
}
V5 V5local;
V5local.del_1 = S2;
V5local.Update_V4(S1,S2,S3,S4);
V5ref[S5].push_back(V5local);
return true;
}
I tried using vector V5ref[2];
It works for 1st iteration and throws error "assert" for 2nd iteration, what could be the reason. is there any other option to have copies of vectors.
what exactly I want to do is, with parameter S2 being 1, 2, 3, I want diff arrays of the whole vector for S2 = 1, S2 = 2...V5 and it's components should be seperate elements of the array according to S2
I have researched your problem a bit. Since the code is insufficient, we all can only guess what you are doing or not doing there. The debug assertion usually comes if the vector has not enough space allocated. (correct me if I am wrong). So, in this case, before using your vectors, you should use the resize(); method. Here is an example:
struct structure
{
int value1;
char value2;
bool value3;
};
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<structure> vector1;
vector1.resize(1);
vector1[0].value1 = 12;
vector1[0].value2 = 'h';
vector1[0].value3 = true;
return 0;
}
If you test it yourself, you will know that without the vector.resize(1); this won't work at the run-time.
At any given time, a std::vector<> has a constraint, size which is the maximum element number you can access + 1, and a constraint capacity which is how many elements it can contain before it has to move the data to a larger memory allocation.
size determines what you can access. When the vector is created, you cannot access anything. vec[0] is illegal when the vector is empty.
#include <vector>
#include <iostream>
int main()
{
std::vector<int> vec;
std::cout << "initially, vec.size = " << vec.size() << ", cap = " << vec.capacity() << "\n";
// initially, the vector is empty.
// std::cout << vec[0] << '\n'; // undefined behavior, probably a crash
// you can only ever access vec[n] where v < vec.size(),
// this vector is empty, so size() == 0
// Lets add a number to the vector.
vec.push_back(5);
std::cout << "now, vec.size = " << vec.size() << ", cap = " << vec.capacity()
std::cout << "vec[0] = " << vec[0] << '\n';
// std::cout << vec[1] << '\n'; // undefined behavior because 1 >= size()
vec.resize(5);
std::cout << "resized, vec.size = " << vec.size() << ", cap = " << vec.capacity()
vec[1] = 1; // valid, resize made space for vec[0] .. vec[4]
vec[2] = 2;
for (auto it = vec.begin(), end = vec.end(); it != end; ++it)
std::cout << *it << '\n';
return 0;
}
push_back does "vec.resize(vec.size() + 1)" for you, and then inserts the value being 'push_back'ed into the new slot.
resize attempts to make room for extra elements -- if size is 3 and you say resize(5) it will try to make room for 2 new elements.
If the result causes size to exceed capacity then the vector allocates a new array, copies the old data over into it, and releases the old array. This can become very expensive. If you know roughly how big your vector is going to become, you can avoid this relocation by calling reserve()
#include <iostream>
#include <vector>
using std::cout;
struct Stud // will always tell you when it reproduces
{
int m_i;
Stud() : m_i(-1) {}
Stud(int i) : m_i(i) {}
Stud(const Stud& rhs) : m_i(rhs.m_i) { cout << "Copying(Ctor) " << m_i << '\n'; }
Stud& operator=(const Stud& rhs) { m_i = rhs.m_i; cout << "Copying(=) " << m_i << '\n'; return *this; }
};
int main()
{
std::vector<Stud> studs;
studs.push_back(0);
studs.push_back(1);
studs.reserve(5);
studs.push_back(5); // remember, this adds to the back.
studs.push_back(6);
std::cout << "size of studs " << studs.size();
return 0;
}
Based on this
bool Update_V4(USHORT S1,USHORT S2,DWORD S3,USHORT S4);
I am guessing that you are trying to simulate multi-dimensional arrays of some kind, and you are doing something like
V4Ref[S1]
without checking
if (S1 < V4Ref.size())
C++ has a function 'assert' which will cause a Debug build application to terminate if a condition is not met.
#include <cassert>
#include <vector>
int main()
{
std::vector<int> vec;
assert(vec.size() == 0);
vec.push_back(1);
vec.resize(5);
vec.push_back(5);
assert(vec.size() == 10); // expect to crash here.
return 0;
}
You could use this to help catch bad sizes:
bool V4::Update_V4(USHORT S1,USHORT S2,DWORD S3,USHORT S4)
{
assert(S1 < V4ref.size());
return V4ref[S1].Update_V3(S2, S3, S4);
}

STL non-copying wrapper around an existing array?

Is it possible to create an STL-like container, or even just an STL-style iterator, for an existing array of POD-type elements?
For example, suppose I have an array of ints. It would be convenient to be able to call some of the STL functions, such as find_if, count_if, or sort directly on this array.
Non-solution: copying the entire array, or even just references to the elements. The goal is to be very memory- and time-saving while hopefully allowing use of other STL algorithms.
You can call many of the STL algorithms directly on a regular C style array - they were designed for this to work. e.g.,:
int ary[100];
// init ...
std::sort(ary, ary+100); // sorts the array
std::find(ary, ary+100, pred); find some element
I think you'll find that most stuff works just as you would expect.
You can use an inline function template so that you don't have to duplicate the array index
template <typename T, int I>
inline T * array_begin (T (&t)[I])
{
return t;
}
template <typename T, int I>
inline T * array_end (T (&t)[I])
{
return t + I;
}
void foo ()
{
int array[100];
std::find (array_begin (array)
, array_end (array)
, 10);
}
All the STL algorithms use iterators.
A pointer is a valid iterator into an array of objects.
N.B.The end iterator must be one element past the end of the array. Hence the data+5 in the following code.
#include <algorithm>
#include <iostream>
#include <iterator>
int main()
{
int data[] = {4,3,7,5,8};
std::sort(data,data+5);
std::copy(data,data+5,std::ostream_iterator<int>(std::cout,"\t"));
}
You can use Boost.Array to create a C++ array type with STL semantics.
using arrays:
int a[100];
for (int i = 0; i < 100; ++i)
a[i] = 0;
using boost.arrays:
boost::array<int,100> a;
for (boost::array<int,100>::iterator i = a.begin(); i != a.end(); ++i)
*i = 0;
Update: With C++11, you can now use std::array.
A pointer is a valid model of an iterator:
struct Bob
{ int val; };
bool operator<(const Bob& lhs, const Bob& rhs)
{ return lhs.val < rhs.val; }
// let's do a reverse sort
bool pred(const Bob& lhs, const Bob& rhs)
{ return lhs.val > rhs.val; }
bool isBobNumberTwo(const Bob& bob) { return bob.val == 2; }
int main()
{
Bob bobs[4]; // ok, so we have 4 bobs!
const size_t size = sizeof(bobs)/sizeof(Bob);
bobs[0].val = 1; bobs[1].val = 4; bobs[2].val = 2; bobs[3].val = 3;
// sort using std::less<Bob> wich uses operator <
std::sort(bobs, bobs + size);
std::cout << bobs[0].val << std::endl;
std::cout << bobs[1].val << std::endl;
std::cout << bobs[2].val << std::endl;
std::cout << bobs[3].val << std::endl;
// sort using pred
std::sort(bobs, bobs + size, pred);
std::cout << bobs[0].val << std::endl;
std::cout << bobs[1].val << std::endl;
std::cout << bobs[2].val << std::endl;
std::cout << bobs[3].val << std::endl;
//Let's find Bob number 2
Bob* bob = std::find_if(bobs, bobs + size, isBobNumberTwo);
if (bob->val == 2)
std::cout << "Ok, found the right one!\n";
else
std::cout << "Whoops!\n";
return 0;
}