When using arrays you can do something like
class SomeClass
{
public:
int* LockMember( size_t& numInts );
private:
int* member;
size_t numInts;
};
int* SomeClass::LockMember( size_t& out_numInts )
{
out_numInts = numInts - 1;
return member + 1;
}
To return an array offset by some amount so as to prevent someone from modifying some part of contingeous memory, or, atleast, show some intent that this part of contingeous memory of the object should remain untouched.
Since I use vectors everywhere, I am wondering if there was some way to accomplish the same sort of thing:
class SomeClass
{
public:
std::vector<int> LockMember( void );
private:
std::vector<int> member;
};
std::vector<int> SomeClass::LockMember( void )
{
// somehow make a vector with its beginning iterator pointing to member.begin() + 1
// have a size smaller by one, still the same end iterator. The vector must be
// pointing to the same data as in this class as it needs to be modifiable.
return magicOffsetVector;
}
With the commented part replaced by real code. Any ideas?
If I understand you correctly: You want some memory with two parts: At the beginning you want something that can't be touched, and after that you want something that is open for use by client code.
You could do something along the following code. This will give the client code a copy to play with. This does mean you would have to do a lot of copying, though.
class SomeClass
{
public:
std::vector<int> getMember( void ) const;
void setMember(std::vector<int> newContent);
private:
std::vector<int> member;
size_t magicOffset;
};
// Read restricted part
std::vector<int> SomeClass::getMember( void ) const
{
return vector<int>(member.begin() + magicOffset, member.end());
}
// Assign to restricted part
void SomeClass::setMember(const std::vector<int>& v)
{
std::copy(v.begin(), v.end(), member.begin() + magicOffset);
}
In order to avoid the copying, it is possible that you could allocate memory for two vectors, one for the protected part and one for the unprotected part, and use placement new to put both vectors into that memory, thus ensuring that they are in contiguous memory. And then give the client code more or less free access to the public part of the vector. However, there's still the thing with bookkeeping variables in vector, and basically this would be an awful hack that's just waiting to blow up.
However, if you only need access to the unrestricted part on a per-element basis, you could just do range-checking on the arguments, i.e.:
int getElement(size_t idx)
{
idx += magicOffset;
if (idx > member.size() || idx < 0) throw std::out_of_range("Illegal index");
return member[idx];
}
And then either provide a setElement, or return int&.
Related
I'm trying to implement my own math library, and I'm starting off with vectors. The idea is to give the class a pointer to an array of numbers, then copy the array and store it in the data address given by a private variable pointer. To begin with, I used alloca to try and free up some memory for the private variable
vml.h
namespace vml {
// Vectors
template <typename in_type, const int in_length>
class vec {
public:
vec(in_type* in_data) {
std::cout << data << std::endl;
std::copy(in_data, in_data + in_length, data);
}
vec() {
data = nullptr;
}
in_type& operator()(int index) const {
_ASSERT(0 <= index && index < in_length);
return data[index];
}
private:
in_type* data = alloca(in_length * sizeof(in_type));
};
main.cpp
int main() {
int list[] = { 1,2,3 };
int list2[] = {2,4,6 };
vml::vec<int, 3> a(list);
vml::vec<int, 3> b(list);
return 0;
}
This gives no errors however, for some reason, alloca returns the same address twice when calling two instances. I searched this up everywhere and I couldn't find an explanation why. So I decided to allocate memory using an array. If you can answer this question that would be extremely helpful.
Thanks.
You have to be very careful with alloca. It allocates memory on the stack rather than the heap. That memory is freed as soon as the function which called alloca exits. In this case, it will be called in the constructor so when you call operator() that memory has already been freed and you are dealing with undefined behavior.
Unless you really need to avoid heap allocations and you know for sure that you wont overflow the stack and you understand all the limitations of using alloca, it's best to steer clear of it.
Lets start with the basics, your stack is most likely only 1 MB, so after a few vectors and recursive calls you program will likely die.
To solve it if you want it on stack you could use std::array as data
Warning untested code ahead
template <typename in_type, const int in_length>
class vec {
public:
vec(in_type* in_data) {
std::cout << data << std::endl;
std::copy(in_data, in_data + in_length, data);
}
vec() = default;
in_type& operator()(int index) const {
_ASSERT(0 <= index && index < in_length);
return data[index];
}
private:
std::array<in_type, in_length> data;
};
Alternatively if you want to use all the nice things from std::array
template <typename in_type, const int in_length>
class vec : public std::array<in_type, in_length> {
public:
using std::array::array; // use constructors, might need template param to compile
}
This also means that if you at some point just want to change to heap you just allocate your vec as every other class.
Another alternative is to use C++17 PMR, use an allocation on the stack as the storage and make vec PMR aware.
You cannot wrap alloca in a function and return its pointer outside, since the stack of wrapper function would be freed.
If you call it as member initializer, it is actually called from constructor, and may be freed when constructor returns and then re-used.
How do I get the position of an element inside a vector, where the elements are classes. Is there a way of doing this?
Example code:
class Object
{
public:
void Destroy()
{
// run some code to get remove self from vector
}
}
In main.cpp:
std::vector<Object> objects;
objects.push_back( <some instances of Object> );
// Some more code pushing back some more stuff
int n = 20;
objects.at(n).Destroy(); // Assuming I pushed back 20 items or more
So I guess I want to be able to write a method or something which is a member of the class which will return the location of itself inside the vector... Is this possible?
EDIT:
Due to confusion, I should explain better.
void Destroy(std::vector<Object>& container){
container.erase( ?...? );
}
The problem is, how can I find the number to do the erasing...? Apparently this isn't possible... I thought it might not be...
You can use std::find to find elements in vector (providing you implement a comparison operator (==) for Object. However, 2 big concerns:
If you need to find elements in a container then you will ger much better performance with using an ordered container such as std::map or std::set (find operations in O(log(N)) vs O(N)
Object should not be the one responsible of removing itself from the container. Object shouldn't know or be concerned with where it is, as that breaks encapsulation. Instead, the owner of the container should concern itself ith such tasks.
The object can erase itself thusly:
void Destroy(std::vector<Object>& container);
{
container.erase(container.begin() + (this - &container[0]));
}
This will work as you expect, but it strikes me as exceptionally bad design. Members should not have knowledge of their containers. They should exist (from their own perspective) in an unidentifiable limbo. Creation and destruction should be left to their creator.
Objects in a vector don't automatically know where they are in the vector.
You could supply each object with that information, but much easier: remove the object from the vector. Its destructor is then run automatically.
Then the objects can be used also in other containers.
Example:
#include <algorithm>
#include <iostream>
#include <vector>
class object_t
{
private:
int id_;
public:
int id() const { return id_; }
~object_t() {}
explicit object_t( int const id ): id_( id ) {}
};
int main()
{
using namespace std;
vector<object_t> objects;
for( int i = 0; i <= 33; ++i )
{
objects.emplace_back( i );
}
int const n = 20;
objects.erase( objects.begin() + n );
for( auto const& o : objects )
{
cout << o.id() << ' ';
}
cout << endl;
}
If you need to destroy the n'th item in a vector then the easiest way is to get an iterator from the beginning using std::begin() and call std::advance() to advance how ever many places you want, so something like:
std::vector<Object> objects;
const size_t n = 20;
auto erase_iter = std::advance(std::begin(objects), n);
objects.erase(erase_iter);
If you want to find the index of an item in a vector then use std::find to get the iterator and call std::distance from the beginning.
So something like:
Object object_to_find;
std::vector<Object> objects;
auto object_iter = std::find(std::begin(objects), std::end(objects), object_to_find);
const size_t n = std::distance(std::begin(objects), object_iter);
This does mean that you need to implement an equality operator for your object. Or you could try something like:
auto object_iter = std::find(std::begin(objects), std::end(objects),
[&object_to_find](const Object& object) -> bool { return &object_to_find == &object; });
Although for this to work the object_to_find needs to be the one from the actual list as it is just comparing addresses.
I'm designing a game in C++ similar to Minecraft that holds an enormous amount of terrain data in memory. In general, I want to store an array in memory that is [5][4][5][50][50][50]. This isn't bad since it amounts to about 100mb of virtual memory since my structure will only be about 8 bytes.
However, I'm having trouble figuring out the best way to handle this. I do want this to be in virtual memory, but obviously not on the stack. And I keep making the mistake some how of creating this array on the stack an causing a stack overflow. What I would like to do is below. This is just code that I threw together to give you an example of what I'm doing, I have code with correct syntax on my machine, I just didn't want to clutter the post.
typedef struct modelBlock
{
// Information about the blocks
} BLOCK;
typedef struct modelGrid
{
bool empty;
BLOCK blocksArray[50][50][50];
} GRID;
class Parent
{
Child* child;
Parent(void);
}
Parent::Parent()
{
Child c;
child = &c;
}
class Child
{
GRID grids[5][4][5];
}
However, every time I do this, I cause a stack overflow (appropriate web site choice right?). I played with using pointer based arrays, but I had a lot of trouble with data being lost outside of its scope.
If anyone could give me some insight on how to get my data to store on the heap instead of the stack, or if I should use some other way of creating my array, I'd really appreciate the help. I'd like to avoid using vectors because of overhead, though I'm not sure how substantial it is.
Use boost::multi_array
If you want to allocate something on the heap, use new.
#include <memory>
class Parent
{
std::auto_ptr<Child> child; // use auto_ptr for dynamically-allocated members
Parent(const Parent&); // You probably don't want to copy this giant thing
public:
Parent();
};
Parent::Parent()
: child(new Child) // initialize members with an initializer list
{
}
Also, avoid mixing C and C++ styles. There's no reason to do
typedef struct blah{ ... } BLAH;
in C++. A struct is just a class with all of the members public by default; just like a class, you can refer to the struct type's name without using the struct tag. There's also no need to specify void for a function that takes no parameters.
boost::multi_array (linked in PigBen's answer) is a good choice over raw arrays.
If you want the class created on the heap, create it with new:
Child * c = new Child;
and then of course delete it, or better still use a smart pointer.
In order to do exactly what you're trying to do you have to declare everything as pointers (and pointers to pointers to pointers to pointers) and then allocate each one individually.
Teh sux!
A better option is to simply allocate the ginormous block in one chunk and use multiple variable along with pointer arithmetic to arrive at the correct location.
Edit: Wasn't paying attention and didn't notice your constructor. That's not only not the way to get your Child allocated on the free-store, it's a great way to create situations eliciting undefined behavior. Your Child will be gone when the constructor is through and the pointer to it will then be invalid. I wonder if you shouldn't run through some basic tutorials before trying to write a game.
Here's something that works and can be built upon without the boost dependency. One downside is it removes use of [][][] style of referencing elements, but it's a small cost and can be added.
template<class T>
class Matrix {
unsigned char* _data;
const size_t _depth;
const size_t _cols;
const size_t _rows;
public:
Matrix(const size_t& depth, const size_t& rows, const size_t& cols):
_depth(depth),
_rows(rows),
_cols(cols) {
_data = new unsigned char [depth * rows * cols * sizeof(T)];
}
~Matrix() {
delete[] _data;
}
T& at(const size_t& depthIndex, const size_t& rowIndex, const size_t& colIndex) const {
return *reinterpret_cast<T*>(_data + ((((depthIndex * _cols + colIndex) * _rows) + rowIndex) * sizeof(T)));
}
const size_t& getDepth() const {
return _depth;
}
const size_t& getRows() const {
return _rows;
}
const size_t& getCols() const {
return _cols;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Matrix<int> block(50, 50, 50);
size_t d, r, c;
for (d = 0; d < block.getDepth(); d++) {
for (r = 0; r < block.getRows(); r++) {
for (c = 0; c < block.getCols(); c++) {
block.at(d, r, c) = d * 10000000 + r * 10000 + c;
}
}
}
for (d = 0; d < block.getDepth(); d++) {
for (r = 0; r < block.getRows(); r++) {
for (c = 0; c < block.getCols(); c++) {
assert(block.at(d, r, c) == d * 10000000 + r * 10000 + c);
}
}
}
return 0;
}
A smaller example (with changed names for all the structs, to make the general principle clearer). The 'Bloe' struct is the one you want to allocate on the heap, and this is accomplished using 'new'.
struct Bla {
int arr[4][4];
};
struct Bloe {
Bla bla[2][2];
};
int main()
{
Bloe* bloe = new Bloe();
bloe->bla[1][1].arr[1][1] = 1;
return 0;
}
I did this by putting all the data in a binary file. I calculated the offset of the data and used seek() and read() to get the data when needed. The open() call is very slow so you should leave the file open during the lifetime of the program.
Below is how I understood what you showed you were trying to do in your example. I tried to keep it straightforward. Each Array of [50][50][50] is allocated in one memory chunk on the heap, and only allocated when used. There is also an exemple of access code. No fancy boost or anything special, just basic C++.
#include <iostream>
class Block
{
public:
// Information about the blocks
int data;
};
class Grid
{
public:
bool empty;
Block (*blocks)[50][50];
Grid() : empty(true) {
}
void makeRoom(){
this->blocks = new Block[50][50][50];
this->empty = false;
}
~Grid(){
if (!this->empty){
delete [] this->blocks;
}
}
};
class Parent
{
public:
Grid (* child)[4][5];
Parent()
{
this->child = new Grid[5][4][5];
}
~Parent()
{
delete [] this->child;
}
};
main(){
Parent p;
p.child[0][0][0].makeRoom();
if (!p.child[0][0][0].empty){
Block (* grid)[50][50] = p.child[0][0][0].blocks;
grid[49][49][49].data = 17;
}
std::cout << "item = "
<< p.child[0][0][0].blocks[49][49][49].data
<< std::endl;
}
This could still be more simple and straightfoward and just use one bug array of [50][50][50][5][4][5] blocks in one memory chunk on the heap, but I'll let you figure out how if this is what you want.
Also, usind dynamic allocation in class Parent only has the sole purpose to use heap instaed of stack, but for such a small array (5*4*5 pointers), allocating it on stack should not be a problem, hence it could be written.
class Parent
{
public:
Grid child[5][4][5];
};
without changing anything in the way it is used.
Suppose you have a function, and you call it a lot of times, every time the function return a big object. I've optimized the problem using a functor that return void, and store the returning value in a public member:
#include <vector>
const int N = 100;
std::vector<double> fun(const std::vector<double> & v, const int n)
{
std::vector<double> output = v;
output[n] *= output[n];
return output;
}
class F
{
public:
F() : output(N) {};
std::vector<double> output;
void operator()(const std::vector<double> & v, const int n)
{
output = v;
output[n] *= n;
}
};
int main()
{
std::vector<double> start(N,10.);
std::vector<double> end(N);
double a;
// first solution
for (unsigned long int i = 0; i != 10000000; ++i)
a = fun(start, 2)[3];
// second solution
F f;
for (unsigned long int i = 0; i != 10000000; ++i)
{
f(start, 2);
a = f.output[3];
}
}
Yes, I can use inline or optimize in an other way this problem, but here I want to stress on this problem: with the functor I declare and construct the output variable output only one time, using the function I do that every time it is called. The second solution is two time faster than the first with g++ -O1 or g++ -O2. What do you think about it, is it an ugly optimization?
Edit:
to clarify my aim. I have to evaluate the function >10M times, but I need the output only few random times. It's important that the input is not changed, in fact I declared it as a const reference. In this example the input is always the same, but in real world the input change and it is function of the previous output of the function.
More common scenario is to create object with reserved large enough size outside the function and pass large object to the function by pointer or by reference. You could reuse this object on several calls to your function. Thus you could reduce continual memory allocation.
In both cases you are allocating new vector many many times.
What you should do is to pass both input and output objects to your class/function:
void fun(const std::vector<double> & in, const int n, std::vector<double> & out)
{
out[n] *= in[n];
}
this way you separate your logic from the algorithm. You'll have to create a new std::vector once and pass it to the function as many time as you want. Notice that there's unnecessary no copy/allocation made.
p.s. it's been awhile since I did c++. It may not compile right away.
It's not an ugly optimization. It's actually a fairly decent one.
I would, however, hide output and make an operator[] member to access its members. Why? Because you just might be able to perform a lazy evaluation optimization by moving all the math to that function, thus only doing that math when the client requests that value. Until the user asks for it, why do it if you don't need to?
Edit:
Just checked the standard. Behavior of the assignment operator is based on insert(). Notes for that function state that an allocation occurs if new size exceeds current capacity. Of course this does not seem to explicitly disallow an implementation from reallocating even if otherwise...I'm pretty sure you'll find none that do and I'm sure the standard says something about it somewhere else. Thus you've improved speed by removing allocation calls.
You should still hide the internal vector. You'll have more chance to change implementation if you use encapsulation. You could also return a reference (maybe const) to the vector from the function and retain the original syntax.
I played with this a bit, and came up with the code below. I keep thinking there's a better way to do this, but it's escaping me for now.
The key differences:
I'm allergic to public member variables, so I made output private, and put getters around it.
Having the operator return void isn't necessary for the optimization, so I have it return the value as a const reference so we can preserve return value semantics.
I took a stab at generalizing the approach into a templated base class, so you can then define derived classes for a particular return type, and not re-define the plumbing. This assumes the object you want to create takes a one-arg constructor, and the function you want to call takes in one additional argument. I think you'd have to define other templates if this varies.
Enjoy...
#include <vector>
template<typename T, typename ConstructArg, typename FuncArg>
class ReturnT
{
public:
ReturnT(ConstructArg arg): output(arg){}
virtual ~ReturnT() {}
const T& operator()(const T& in, FuncArg arg)
{
output = in;
this->doOp(arg);
return this->getOutput();
}
const T& getOutput() const {return output;}
protected:
T& getOutput() {return output;}
private:
virtual void doOp(FuncArg arg) = 0;
T output;
};
class F : public ReturnT<std::vector<double>, std::size_t, const int>
{
public:
F(std::size_t size) : ReturnT<std::vector<double>, std::size_t, const int>(size) {}
private:
virtual void doOp(const int n)
{
this->getOutput()[n] *= n;
}
};
int main()
{
const int N = 100;
std::vector<double> start(N,10.);
double a;
// second solution
F f(N);
for (unsigned long int i = 0; i != 10000000; ++i)
{
a = f(start, 2)[3];
}
}
It seems quite strange(I mean the need for optimization at all) - I think that a decent compiler should perform return value optimization in such cases. Maybe all you need is to enable it.
I'm an intermittent programmer and seem to have forgotten a lot of basics recently.
I've created a class SimPars to hold several two-dimensional arrays; the one shown below is demPMFs. I'm going to pass a pointer to an instance of SimPars to other classes, and I want these classes to be able to read the arrays using SimPars accessor functions. Speed and memory are important.
I know life is often simpler with vectors, but in this case, I'd really like to stick to arrays.
How do I write the accessor functions for the arrays? If I'm interested in the nth array index, how would I access it using the returned pointer? (Should I write a separate accessor function for a particular index of the array?) What's below is certainly wrong.
// SimPars.h
#ifndef SIMPARS_H
#define SIMPARS_H
#include "Parameters.h" // includes array size information
class SimPars {
public:
SimPars( void );
~SimPars( void );
const double [][ INIT_NUM_AGE_CATS ] get_demPMFs() const;
private:
double demPMFs[ NUM_SOCIODEM_FILES ][ INIT_NUM_AGE_CATS ];
};
#endif
// SimPars.cpp
SimPars::SimPars() {
demPMFs[ NUM_SOCIODEM_FILES ][ INIT_NUM_AGE_CATS ];
// ...code snipped--demPMFs gets initialized...
}
//...destructor snipped
const double [][ INIT_NUM_AGE_CATS ] SimPars::get_demPMFs( void ) const {
return demPMFs;
}
I would greatly appreciate some kind of explanation with proposed solutions.
Basically, you have three options: return the entire array by reference, return the first row by pointer, or return the entire array by pointer. Here is the implementation:
typedef double array_row[INIT_NUM_AGE_CATS];
typedef array_row array_t[NUM_SOCIODEM_FILES];
array_t demPMFs;
const array_t& return_array_by_reference() const
{
return demPMFs;
}
const array_row* return_first_row_by_pointer() const
{
return demPMFs;
}
const array_t* return_array_by_pointer() const
{
return &demPMFs;
}
And here are the use cases:
SimPars foo;
double a = foo.return_array_by_reference()[0][0];
double b = foo.return_first_row_by_pointer()[0][0];
double c = (*foo.return_array_by_pointer())[0][0];
How would I return just the nth row of the array?
Again, you have three choices:
const array_row& return_nth_row_by_reference(size_t row) const
{
return demPMFs[row];
}
const double* return_first_element_of_nth_row_by_pointer(size_t row) const
{
return demPMFs[row];
}
const array_row* return_nth_row_by_pointer(size_t row) const
{
return demPMFs + row;
}
const double (* get_demPMFs() const)[INIT_NUM_AGE_CATS];
Or, use typedef (but that doesn't seems cleaner...).
class SimPars {
typedef const double (*ConstDemPMFType)[INIT_NUM_AGE_CATS];
double demPMFs[NUM_SOCIODEM_FILES][INIT_NUM_AGE_CATS];
public:
ConstDemPMFType get_demPMFs() const;
};
Note that you can't return an array (g++ refuses the compile). But an array of array can be decayed to a pointer to array, so the latter is returned.
Logically speaking there is this question with a data member. Should users be allowed to modify it or not. If you want to give another class full access to the member, you don't necessarily need getter/setter, especially if you are the only user. You can just make the member public.
If your class would be better off controlling how users access the member, then you could use a getter only to enforce read only access. The simplest way to do this if you don't want to get all confused about the 2-dimensional arrays is to just have an inline function fetching the element for the user class:
const double& getElem( int x, int y ) const { return demPMF[x][y] }
It makes sense to do bounds checking here, but considering that you insist on using arrays, and if your profiler proves that you can't afford it, this function would just allow access to your array.
If you want further elaboration, post a comment...