Private vector in class - c++

class MyStrValArray
{
private:
vector<char> p;
public:
void init(const int n);
void clear();
unsigned capacity();
unsigned size();
};
I want to have a vector as private class member, and in the public part, I want to declare the size(const int n) of the vector. Is there a way to do this?
And the reason I want to use vector is, I need to get the size / capacity of the memory, resize, or remove the nth element of the memory. Is it right to use vector in this case?

If you are trying to implement custom string implementation then ,having "char * data" is more appropriate.
Otherwise you can use vector like this :
#include <iostream>
#include <vector>
using namespace std;
class MyStrValArray
{
private:
vector<char> p;
public:
MyStrValArray() {}
MyStrValArray(const int sz ) : p(sz){}
void init(const int n)
{
p.resize(n);
}
void clear()
{
p.clear();
}
unsigned capacity()
{
return p.capacity();
}
unsigned size()
{
return p.size();
}
};
int main()
{
MyStrValArray ma;
ma.init(4);
std::cout<<ma.size()<<std::endl;
return 0;
}

Related

C++ Initiating object with array in constructor

I am trying to initiate an object with an array. Is there a way to do it with pointers or should i find another way to do this.
EDIT: I want to write this code with dynamic memory allocation, I know vector is better way to solve this.
#include <iostream>
template <class t>
class die {
private:
int sideCount;
t* valueOfSides;
public:
die(int side, t arr[]) {
sideCount = side;
valueOfSides = (t*)malloc(side * sizeof(t));
for (int counter; counter < side; counter++) {
valueOfSides[counter] = val[counter];
}
}
~die() {
free(valueOfSides);
}
};
int main() {
die<int> sixsided(6, {1,2,3,4,5,6});
}
The right ways to do this would be
std::vector<t> valueOfSides;
template<size_t len> die(t (&arr)[len])
: valueOfSides(std::begin(arr), std::end(arr))
{}
or
std::vector<t> valueOfSides;
die(std::initializer_list<t> arr) : valueOfSides(arr) {}
I think. Though really, the best answer is
std::vector<t> valueOfSides;
die(std::vector<t> arr) : valueOfSides(std::move(arr)) {}
One should never use raw pointers to own memory in C++, and virtually never use new or malloc. As it is, you have undefined behavior in your code because of misusing malloc.
If you're absolutely insane, or doing homework, it can be done with raw pointers, though I doubt I can get it entirely right without tests and a compiler.
template<class t>
class die {
private:
int sideCount;
t* valueOfSides;
public:
die(int side, t* arr) {
sideCount = 0;
std::size_t buffer_size = sizeof(t)*side;
char* buffer;
try {
buffer = new char[side];
valueOfSides = reinterpret_cast<t*>(buffer);
for(int i=0; i<side; i++) {
new(valueOfSides+i)t(arr[i]);
sideCount++;
}
} catch(...) {
for(int i=sideCount; i>=0; i--)
(valueOfSides+i)->~t();
delete[]buffer;
throw;
}
}
die& operator=(die&& rhs) {
sideCount = rhs.sideCount;
valueOfSides = rhs.valueOfSides;
rhs.valueOfSides = nullptr;
rhs.sideCount = 0;
return *this;
}
//die& operator=(const die& rhs) not shown because its super hard.
~die() {
for(int i=sideCount; i>=0; i--)
(valueOfSides+i)->~t();
delete[]reinterpret_cast<char*>(valueOfSides);
}
};
As we've said before, getting this stuff right is crazy hard. Use a std::vector.
Use std::vector.
#include <iostream>
#include <initalizer_list>
#include <vector>
template<class T>
class die {
public:
die() = default;
die(std::initializer_list<T> list)
: sides{list}
{ /* DO NOTHING */ }
private:
std::vector<T> sides{};
};
int main() {
die<int> sixsided({1,2,3,4,5,6});
}
One way you can do this, using more of a C technique, is a variable argument list:
#include <cstdarg>
#include <iostream>
template <class t>
class die {
private:
int sideCount;
t* valueOfSides;
public:
die(int side, ...) {
sideCount = side;
valueOfSides = new t[side];
va_list args;
va_start(args, side);
for (int counter = 0; counter < side; counter++) {
valueOfSides[counter] = va_arg(args, t);
}
va_end(args);
}
~die() {
delete[] valueOfSides;
}
};
int main() {
die<int> sixsided(6, 1,2,3,4,5,6);
}
Rather than passing an array, you're passing the parameters individually (i.e. no need for a temporary array) and using a va_list to access them.
Also, the calls to malloc and free were replaced with new and delete which is the C++ way of allocating and deallocating memory.
The C++ solution:
template <class t>
class die {
private:
int sideCount;
t* valueOfSides;
public:
die(int side, t arr[]) {
sideCount = side;
valueOfSides = new T[side]
for (int counter = 0; counter < side; counter++) { //always initialize variables
valueOfSides[i] = arr[i];
}
}
~die() {
delete[] valueOfSides;
}
};
int main() {
int arr[6] = { 1,2,3,4,5,6 };
die<int> sixsided(6, arr);
}
The new operator is like malloc and the delete and delete[] operators are like free. They are dynamic allocators.
C solution:
template <class t>
class die {
private:
int sideCount;
t* valueOfSides;
public:
die(int side, t arr[]) {
sideCount = side;
valueOfSides = (t*)malloc(side * sizeof(t));
for (int counter = 0; counter < side; counter++) { //always initialize variables
valueOfSides[i] = arr[i];
}
}
~die() {
free(valueOfSides);
}
};
int main() {
int arr[6] = { 1,2,3,4,5,6 };
die<int> sixsided(6, arr);
}
Note: in C the <iostream> header will not work, this is C++ only.
There are other containers, namely std::vector, that can work, but this is the solution for your answer.

Why doesn't my priority_queue which contains my class objects in C++ work correctly? [duplicate]

So I'm using the STL priority_queue<> with pointers... I don't want to use value types because it will be incredibly wasteful to create a bunch of new objects just for use in the priority queue. So... I'm trying to do this:
class Int {
public:
Int(int val) : m_val(val) {}
int getVal() { return m_val; }
private:
int m_val;
}
priority_queue<Int*> myQ;
myQ.push(new Int(5));
myQ.push(new Int(6));
myQ.push(new Int(3));
Now how can I write a comparison function to get those to be ordered correctly in the Q? Or, can someone suggest an alternate strategy? I really need the priority_queue interface and would like to not use copy constructors (because of massive amounts of data). Thanks
EDIT: Int is just a placeholder/example... I know I can just use int in C/C++ lol...
You can explicitly specify which comparator your queue should use.
#include <iostream>
#include <sstream>
#include <functional>
#include <vector>
#include <queue>
class Int {
public:
Int(int val) : m_val(val) {}
int getVal() { return m_val; }
bool operator<(const Int &other) const { return m_val < other.m_val; }
private:
int m_val;
};
template<typename Type, typename Compare = std::less<Type> >
struct pless : public std::binary_function<Type *, Type *, bool> {
bool operator()(const Type *x, const Type *y) const
{ return Compare()(*x, *y); }
};
int main(int argc, char *argv[]) {
std::priority_queue<Int*, std::vector<Int*>, pless<Int> > myQ;
for (int i = 1; i < argc; i++) {
std::stringstream ss(argv[i]);
int x;
ss >> x;
myQ.push(new Int(x));
}
for (; !myQ.empty(); delete myQ.top(), myQ.pop())
std::cout << myQ.top()->getVal() << std::endl;
return 0;
}
One option that will surely work is to replace Int* with shared_ptr<Int> and then implement operator< for shared_ptr<Int>
bool operator<(const shared_ptr<Int> a, const shared_ptr<Int> b)
{
return a->getVal() < b->getVal();
}
An integer is the same size as a pointer on 32 bit systems. On 64 bit systems, a pointer will be twice as big. Therefore, it is simpler/faster/better to use regular integers.

dealing with dynamically allocated array of objects of a class in another class

I want the bag class to have an array of item objects that is dynamically allocated but not sure how to do this. Also need someone to have a look at the rest of my code. I want to add Item objects to a Bag object and perform operations on the thus formed ADT as is evident from the code.
Item.h
#ifndef ITEM_H
#define ITEM_H
class Item
{
char* item_name;
public:
Item(char *name);
void display_item(Item i);
~Item();
protected:
private:
};
#endif
Item.cpp
#include "Item.h"
#include<string.h>
#include<iostream>
#include<malloc.h>
using namespace std;
Item::Item(char* name)
{
item_name = new char[sizeof(name)];
strcpy(item_name,name);
}
void Item::display_item(Item i)
{
cout<<i.item_name<<" ";
}
Item::~Item()
{
}
Bag.h
#include "Item.h"
#ifndef BAG_H
#define BAG_H
class Bag
{
int no_of_items;
int capacity;
Item list[];
public:
Bag(int no_of_items);
void add(Item i);
void display();
~Bag();
protected:
private:
};
#endif
Bag.cpp
#include "Bag.h"
#include "Item.h"
#include<malloc.h>
Bag::Bag(int capacity)
{
Item list[capacity];
no_of_items =0;
}
void Bag::add(Item i)
{
if(no_of_items<capacity)
{
list[no_of_items] = i;
no_of_items++;
}
else
{
cout<<"bag is full";
}
}
void Bag:: display()
{
for(i=0;i<no_of_items;i++)
{
display_item(list[i]);
}
}
Bag::~Bag()
{
//dtor
}
I'll not speak on your code, if you have problems with it, ask in a separate question with minimal code to reproduce the error. Here is a link, at the end of this answer, explaining how to dynamically allocate memory for your array. If you are doing so because you need a variable sized array, I would recommend a vector. While an object of type array must have the size defined at compile time, a vector does not have this requirement, and you can use vector_pushback to add new elements with ease. But if you insist on using an array, follow the instructions here: http://www.cplusplus.com/forum/articles/416/
As possible, always use STL containers. They have analogous interface and are well documented. Most of them are dynamic. So, your code with STL containers (std::string and std::vector) could look like:
#include <string>
#include <vector>
#include <iostream>
class Item {
public:
Item(const std::string& name) : item_name(name) {}
virtual ~Item() {}
void display_item() {
std::cout << item_name << " ";
}
private:
std::string item_name;
};
class Bag {
public:
void add(const Item& i) {
items.push_back(i);
}
void display() {
for(std::vector<Item>::iterator it = items.begin();
it != items.end(); ++it)
it->display_item();
}
private:
std::vector<Item> items;
};
As your question is aiming on how to implement your example with dynamic allocation, the code above without STL containers can be done as:
#include <cstring>
#include <algorithm>
#include <iostream>
class Item {
public:
Item() : item_name(0) {} // required for new[] expression
Item(const char* name) : item_name(0) {
copyName(name);
}
virtual ~Item() {
delete[] item_name; // don't forget to free the allocated memory
}
void display_item() const {
std::cout << item_name << " ";
}
Item& operator=(const Item& other) { // required for copying
copyName(other.item_name);
return *this;
}
private:
void copyName(const char* str) {
// get the size of the new name and delete the actual name
const size_t name_size = strlen(str);
delete[] item_name;
// allocate memory for new name and copy it
item_name = new char[name_size + 1]; // extra place for '\0'
strcpy(item_name, str);
}
char* item_name;
};
class Bag {
public:
Bag(size_t cap = 0) :
items(cap ? new Item[cap] : 0), capacity(cap), size(0) {}
virtual ~Bag() {
delete[] items;
}
void add(const Item& i) {
// "resize" the actual array if there is no space for a new item
if(size == capacity) {
// allocate new array and copy the actual content
capacity += 100;
Item* temp = new Item[capacity];
std::copy(items, items + size, temp);
// delete the actual array and assign the newly allocated one
delete[] items;
items = temp;
temp = 0;
}
// add the new item
items[size] = i;
size++;
}
void display() {
for(size_t i = 0; i < size; ++i)
items[i].display_item();
}
private:
Item* items;
size_t capacity;
size_t size;
};

Sort vector of class

Before I get my fair share of "this is a duplicate of link-to-thread" replies, I'd like to say that I've implemented both what I have been reading on StackOverflow and on the CPlusPlus website. The problem is that my vector won't sort. I must be missing something in the implementation. Maybe incorrect use of references etc.
Here goes: I have two classes - DETargetParam and a wrapper class named DETargetParamVector that includes an STL vector of type DETargetParam. My objective is to sort the std::vector in ascending order using the fitness member variable of DETargetParam. I've tried to do that by overloading the less than operator in the DETargetParam class and returning a boolean result.
This, however, does not sort. Everything compiles and executes perfectly, but there's no sort. I really hope someone here can help me.
This is the source code for DETargetParam:
#ifndef _DE_TARGET_PARAM_H_DP_
#define _DE_TARGET_PARAM_H_DP_
template <typename T, unsigned int N>
class DETargetParam {
private:
/** The array of N parameters in type T */
T param[N];
long double fitness;
long double probability;
long double probabilityInterval;
public:
/**
* #brief Default constructor.
*
* Nada!
*/
DETargetParam() {
/* NULL */
}
long double getFitness() {
return fitness;
}
void setFitness(long double x) {
fitness = x;
}
long double getProbability() {
return probability;
}
void setProbability(long double x) {
probability = x;
}
long double getProbabilityInterval() {
return probabilityInterval;
}
void setProbabilityInterval(long double x) {
probabilityInterval = x;
}
bool operator<(const DETargetParam& rhs) const {
return (fitness < rhs.fitness);
}
T& operator[](unsigned int i) {
return param[i];
}
};
#endif // _DE_TARGET_PARAM_H_DP_
and the DETargetParamVector wrapper class:
#ifndef _DE_TARGET_PARAM_VECTOR_H_DP_
#define _DE_TARGET_PARAM_VECTOR_H_DP_
#include <algorithm>
#include <cstdio>
#include <vector>
#include "DETargetParam.h"
template <typename T, unsigned int N, unsigned int NP>
class DETargetParamVector {
private:
/** This is a STL vector holding the parameters */
std::vector< DETargetParam<T, N> > vec;
public:
/**
* #brief Default constructor
*
* Move along... nothing to see here.
*/
DETargetParamVector() {
vec.reserve(NP);
}
void SortAndCalculate() {
SortVector();
PrintSorted();
}
void SortVector() {
std::sort(vec.begin(), vec.end());
}
void PrintSorted() {
for (unsigned int i = 0; i < NP; ++i) {
fprintf(stdout, "%.12Lf, %.12Lf, %.12Lf\n", vec[i].getFitness(), vec[i].getProbability(), vec[i].getProbabilityInterval());
}
fprintf(stdout, "\n");
fflush(stdout);
}
DETargetParam<T, N>& operator[](unsigned int i) {
return vec[i];
}
};
#endif // _DE_TARGET_PARAM_VECTOR_H_DP_
and the main function details:
#include <cmath>
#include <ctime>
#include "DETargetParamVector.h"
const unsigned int N = 10;
const unsigned int NP = 10;
int main() {
srand(time(0));
DETargetParamVector<long double, N, NP> targetVector;
// For each member of the population.
for (unsigned int i = 0; i < NP; ++i) {
targetVector[i].setFitness(static_cast<long double>(rand()));
}
targetVector.SortAndCalculate();
return 0;
}
Thanks in advance.
Your vector does get sorted. The issue is that your vector is empty, and all you do is write and read outside of the vector.
/**
* #brief Default constructor
*
* Move along... nothing to see here.
*/
DETargetParamVector() {
vec.reserve(NP);
}
The comment is quite ironic, because here is your error. vec.reserve(NP) does not change the size of the vector, it just does something to save work in the future. You need to replace reserve with resize, or even better just initialize it from the start:
/**
* #brief Default constructor
*
* Move along... nothing to see here.
*/
DETargetParamVector() : vec(NP) {
}
On a side node, this:
int N = 10;
int NP = 10 * N;
int main() {
DETargetParamVector<long double, N, NP> targetVector;
is illegal, because you have non-const ints as template arguments. You need to replace int N with int const N (likewise for NP).
I've put together a somewhat simplified version of your code, that at least works to generate and sort some objects. I've also (at least IMO) fixed a few places that your design struck me as somewhat problematic (though the result still falls well short of perfect, at least IMO).
de_target_param.h:
#ifndef _DE_TARGET_PARAM_H_DP_
#define _DE_TARGET_PARAM_H_DP_
#include <iostream>
template <typename T, unsigned int N>
class DETargetParam {
private:
/** The array of N parameters in type T */
// T param[N];
long double fitness;
// long double probability;
// long double probabilityInterval;
public:
DETargetParam(long double f) : fitness(f) { }
/*
long double getFitness() {
return fitness;
}
void setFitness(long double x) {
fitness = x;
}
long double getProbability() {
return probability;
}
void setProbability(long double x) {
probability = x;
}
long double getProbabilityInterval() {
return probabilityInterval;
}
void setProbabilityInterval(long double x) {
probabilityInterval = x;
}
*/
friend std::ostream &operator<<(std::ostream &os, DETargetParam const &d) {
return os << d.fitness;
}
bool operator<(const DETargetParam& rhs) const {
return (fitness < rhs.fitness);
}
};
#endif // _DE_TARGET_PARAM_H_DP_
de_target_param_vector.h:
#include "de_target_param.h"
#ifndef _DE_TARGET_PARAM_VECTOR_H_DP_
#define _DE_TARGET_PARAM_VECTOR_H_DP_
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
template <typename T, unsigned int N, unsigned int NP>
class DETargetParamVector {
std::vector< DETargetParam<T, N> > vec;
public:
void push(DETargetParam<T, N> const &d) {
vec.push_back(d);
}
void SortAndCalculate() {
SortVector();
std::cout << *this;
}
void SortVector() {
std::sort(vec.begin(), vec.end());
}
friend std::ostream &operator<<(std::ostream &os, DETargetParamVector const &d) {
std::copy(d.vec.begin(), d.vec.end(), std::ostream_iterator<DETargetParam<T, N> >(os, "\n"));
return os;
}
};
#endif // _DE_TARGET_PARAM_VECTOR_H_DP_
And, I've written a small main that creates, sorts, and prints, (in sorted order) some objects:
#include "de_target_param_vector.h"
int main() {
DETargetParamVector<int, 1, 5> params;
for (int i=0; i<5; i++)
params.push(rand());
params.SortAndCalculate();
return 0;
}
Based on how you designed your DETargetParam class, I think a bit of Googling for "pseudo object oriented" or something similar should turn up some useful, relevant reading. A great deal of your code seems (at least to me) to exemplify the genre.

priority_queue<> comparison for pointers?

So I'm using the STL priority_queue<> with pointers... I don't want to use value types because it will be incredibly wasteful to create a bunch of new objects just for use in the priority queue. So... I'm trying to do this:
class Int {
public:
Int(int val) : m_val(val) {}
int getVal() { return m_val; }
private:
int m_val;
}
priority_queue<Int*> myQ;
myQ.push(new Int(5));
myQ.push(new Int(6));
myQ.push(new Int(3));
Now how can I write a comparison function to get those to be ordered correctly in the Q? Or, can someone suggest an alternate strategy? I really need the priority_queue interface and would like to not use copy constructors (because of massive amounts of data). Thanks
EDIT: Int is just a placeholder/example... I know I can just use int in C/C++ lol...
You can explicitly specify which comparator your queue should use.
#include <iostream>
#include <sstream>
#include <functional>
#include <vector>
#include <queue>
class Int {
public:
Int(int val) : m_val(val) {}
int getVal() { return m_val; }
bool operator<(const Int &other) const { return m_val < other.m_val; }
private:
int m_val;
};
template<typename Type, typename Compare = std::less<Type> >
struct pless : public std::binary_function<Type *, Type *, bool> {
bool operator()(const Type *x, const Type *y) const
{ return Compare()(*x, *y); }
};
int main(int argc, char *argv[]) {
std::priority_queue<Int*, std::vector<Int*>, pless<Int> > myQ;
for (int i = 1; i < argc; i++) {
std::stringstream ss(argv[i]);
int x;
ss >> x;
myQ.push(new Int(x));
}
for (; !myQ.empty(); delete myQ.top(), myQ.pop())
std::cout << myQ.top()->getVal() << std::endl;
return 0;
}
One option that will surely work is to replace Int* with shared_ptr<Int> and then implement operator< for shared_ptr<Int>
bool operator<(const shared_ptr<Int> a, const shared_ptr<Int> b)
{
return a->getVal() < b->getVal();
}
An integer is the same size as a pointer on 32 bit systems. On 64 bit systems, a pointer will be twice as big. Therefore, it is simpler/faster/better to use regular integers.