I've come across a bit of code which essentially looks like this:
#include<iostream>
// in a header file
class xxx{
public:
xxx() { xxx_[0]=0; xxx_[1]=0; xxx_[2]=0;}
double x0() const {return xxx_[0];}
private:
double xxx_[3]; // ???
};
// in the main.cpp
int main(){
xxx x;
std::cout<<x.x0()<<"\n";
}
The question is --- is declaring as a class member an array of fixed size is really allowed by the standard?
There is nothing wrong with the above code. It might not be the best way to write it, but there is nothing intrinsically wrong with it.
Yes, your class xxx may contain a fixed-size array as a member. It's allowed in C too.
The compiler, even when reading the header to use it, knows how big to make sizeof(xxx) as a result.
There is nothing wrong with declaring static array as a member of class:
class A
{
int a[3];
};
It is allowed.
Design-wise, this is often not ideal, though; arrays don't have such a nice interface as std::array has:
std::array<double,3> xxx_;
for (auto it : xxx_) {...}
xxx_.size()
std::transform (xxx_.begin(), xxx_.end(), ...);
etc. So if you find yourself using your (static sized) array as a container most of the time, you should replace it with std::array (which has no spatial overhead). If you need dynamic sized arrays, look at std::vector, which has a small overhead (size + capacity, however, with manual allocation, you must remember the size, too, so the only overhead is capacity).
Related
Background
For an embedded project, I want a class that takes a list of structs. This list is known at compile-time, so I shouldn't have to resort to dynamic memory allocation for this.
However, how do I make a struct/class that encapsulates this array without having to use its size as a template parameter?
Templates
My first idea was to do exactly that:
struct Point {
const uint16_t a;
const double b;
};
template<size_t n>
struct Profile {
Array<Point, n> points;
Profile(const Array<Point, n> &points) : points(points) {}
};
Here, Profile is the class that stores/encapsulates the array of points (the 2-member structs). n, the size of the array, is a template parameter.
I'm using this implementation of Array, similar to std::array, btw, because I don't have access to the STL on this embedded platform.
However, no I have another class that uses this Profile that now also has to be templated because Profile is templated with the size of the array:
template<size_t n>
class Runner {
private:
const Profile<n> profile;
public:
Runner(const Profile<n> &profile) : profile(profile) {};
void foo() {
for(auto point : profile.points) {
// do something
}
}
};
As can be seen, this Runner class operates on a Profile and iterates over it. Having to template Runner is not that much of an issue by itself, but this Runner in turn is used by another class in my project, because this other class calls Runner::foo(). Now I have to template that class as well! And classes that use that class, etc.
That's getting out of hand! What started with just one template parameter to specify the size, now propagates through my entire application. Therefore, I don't think this is a good solution.
Question
Is there a way to 'hide' the size of the array in Profile or Runner? Runner only needs to iterate over it, so the size should in principle only affect its implementation, not its public interface. How would I do that, though?
Also, can I avoid having to manually specify n at all, and just pass an array to Profile's constructor and let the compiler figure out how big it is? At compile-time, of course. I feel like this should be possible (given this array is known at compile-time), but I don't know how exactly.
Other approaches
Macros
I could write a macro like
#define n 12
and include that in both the Profile.h and the place where I instantiate a Profile. This feels dirty though, I and would like to avoid macros.
Vector
I could avoid this fuss by just using a std::vector (or equivalent) instead, but that is allocated at run-time on the heap, which I would like to avoid here since it shouldn't be necessary.
Is there a way to 'hide' the size of the array in Profile or Runner?
Yes. The solution is indirection. Instead of storing the object directly, you can point to it. You don't need to know the size of what you're pointing at.
A convenient solution is to point into dynamic storage (for example std::vector) because it allows you to "bind" the lifetime of the dynamically sized object to a member. That's not necessary in general, and you can use automatic storage instead. However, in that case you cannot bind the lifetime of the pointed object, and you must be very careful to not let the pointed object be destroyed before you stop using it.
The indirection can be done at whatever level you prefer. If you do it at the lowest level, you simply store the array outside of Profile. In fact, if all that profile does is contain an array, then you don't need a class for it. Use a generic span:
struct Runner {
span<const Point> profile;
void foo() {
for(auto point : profile) {
// do something
}
}
};
Point points[] {
// ... number of points doesn't matter
};
Runner runner {
.profile = points,
};
By span, I mean something like std::span. If you cannot use the standard library, then use another implementation. It's basically just a pointer and size, with convenient template constructor.
To clarify, you can pick any two, but you cannot have all three of these:
Lifetime of the array bound to the class (safe)
No compiletime constant size
No dynamic storage
1,2 (no 3) = std::vector, RAII
1,3 (no 2) = std::array, templates, no indirection
2,3 (no 1) = std::span, be careful with lifetimes
I'll expand on this comment:
The idea is that Runner takes Profiles no matter their size. Runner needs to iterate over it, but apart from that, its behaviour is always the same. The class using Runner and calling Runner::foo() doesn't need to know the size. The problem with templating Runner is that the class using Runner also needs to be templated, and the classes using that, etc.
This is only a problem when the class is using the templated Runner directly. It has more dependencies than it actually needs. If it doesn't need to know about the size of the array, then it should not know about the size of the array. If runtime polymorphism is an option you can add a base class that allows accessing the array elements, but doesn't need to know anything about the arrays size. The following is only a sketch:
#include <iostream>
struct RunnerInterface {
virtual int* begin() = 0;
virtual int* end() = 0;
virtual ~RunnerInterface(){}
};
template <unsigned size>
struct Runner : RunnerInterface {
int data[size];
int* begin() override { return data; }
int* end() override { return data+size; } // pointer one past the end if fine (it won't get dereferenced)
};
void foo(RunnerInterface& ri) {
for (auto it = ri.begin(); it != ri.end(); ++it){
*it = 42;
}
}
void bar(RunnerInterface& ri){
for (auto it = ri.begin(); it != ri.end(); ++it){
std::cout << *it;
}
}
int main() {
Runner<42> r;
foo(r);
bar(r);
}
Now if a class needs a Runner member, they store a std::unique_ptr<RunnerInterface> and only on construction you need to decide for the size of the array (though you still need to decide for the size somewhere).
Let's say I have a base class called
Class Base {
public:
std::string array[];
};
The size the string array is not decided until another class extends it, what's the correct syntax for doing so?
EG, later on in a derived class
Derived::Derived() {
array[] = new array[40];
}
If you want to use a C-style array, the size must be fixed and known at compile-time. And even in that case, you could use the safer, zero-overhead std::array<> wrapper instead.
If the size of your container is not known at compile-time, then it is good practice to use std::vector (or std::deque in some cases, based on your requirements in terms of memory allocation) and avoid manual memory management through raw pointers, new[] and delete[]:
#include <string> // For std::string
#include <vector> // For std::vector
class Base {
public:
std::vector<std::string> myVector;
};
Besides, this design won't require any dedicated work in the constructor (and destructor) of Derived. If all that was done by Derived's default constructor was to allocate the array, now you can avoid explicitly defining a default constructor at all, and let the compiler generate one for you implicitly - same story for the destructor.
Also, I would discourage you from using names of standard container classes (like array) as names for your variables. Something like myArray (or myVector, as in my example above) are more appropriate choices.
You don't. Arrays in C++ are of compile-time fixed size. You cannot just resize them to your liking.
The bad way to do this using only language features is to actually have your member as an std::string*:
std::string* array;
And then dynamically allocate an array of std::strings, assigning the pointer to the first element to array:
Derived::Derived() {
array = new std::string[40];
}
The good way to do this is to use library features. The standard library provides container types for you to use. Try a std::vector<std::string>:
std::vector<std::string> array;
Which you could initialise to contain 40 strings like so:
Derived::Derived()
: array(40)
{ }
Why not use a std::vector<std::string> so that you don't have to worry about size. The container resizes automagically as new things are inserted into it.
Using a vector of string is normally better solution.
But this will work:
Class Base {
Public:
std::string *array;
};
Derived::Derived() {
array = new array[40];
}
I'd add:
Class Base {
Public:
std::string *arr;
Base():arr(nullptr){}
Base(sizr_t s):arr(new std::string[s]){}
~Base(){delete []arr;}
};
Derived::Derived():Base(40) { }
And you may need to write copy/move constructors and asignments. Derived dont have to know about very much.
Now compare with:
Class Base {
Public:
std::vector<std::string> arr;
Base(){}
Base(sizr_t s):arr(s){}
};
All other special functions: destructor, copy/move constructors and asignments are generated by compiler. And the constructor of Derived is still:
Derived::Derived():Base(40) { }
Also... you may want to make arr private or at least protected?
The correct syntax is
std::vector<std::string> array;
As well as the done-to-death heap allocation, you can size it statically as in:
template <int N>
class Base
{
public:
std::string array[N];
};
class Derived : Base<40>
{ ... }
Pros: simple, avoids (relatively slow) memory allocation at runtime and the hassles of cleanup (smart array pointer or otherwise). Cons: each instantiation of Base is a distinct type, which can lead to a little more bloat and less interoperability.
i know how to create a stack of vectors or int ,etc. But i dont know how to create a stack of a multidimentional arrays t[n][n] . Whats the way to implement it?
this is my actual implementation which its not working.
char map[20][20];
stack<map> soluciones;
Edit:
I think due my english most of you didnt undestand my question. Imagine i got some kind of a Game map. I am saving each multidimentional array on the stack. Thats my objective saving the map on a stack
Edit 2: im using Visual Studio 2010 Windows form application
In your code example, you use map (the name of your variable) in place of where a type name must stand (in stack<map> template instantiation). However, it won't work, not even if you use the proper type name (in this case you'd have to use typedef, e.g. typedef char TwoDimCharArray[20][20] and then try std::stack<TwoDimCharArray>:
There is still the problem that arrays don't have a default constructor (which std::stack expects); therefore, std::stack cannot be made to directly contain arrays; you'd have to wrap the array inside a class or struct (which can have a default constructor), e.g.:
class TwoDimCharArray
{
public:
// omit if there's nothing to initialize in map, then the
// compiler-generated constructor will be used
TwoDimCharArray()
{
// ... initalize map values
}
// ... provide access methods to map
private:
char map[20][20];
};
std::stack<TwoDimCharArray> soluciones;
Or use Boost.Array or C++11 std::array stuff! If these are available, they are definitely the better and easier choice!
I guess you should define a proper class for the game map. Then the stack of game maps is not a problem.
class GameMap {
public:
...
private:
char map_[1000][1000];
};
Then it wont matter for the stack how you allocate and manage the map data. E.g.
typedef std::stack<GameMap> GameMapStack;
Ddefine a wrapper class for multidimentional arrays like this:
template <class T, int X, int Y>
class Wrapper
{
public:
T array[X][Y];
}
Then use stack<Wrapper<char, 20, 20> >
First create structure and then define an empty multidimensional char array. then close structure and after thar write push and pop operations.
I'm having trouble figuring out which is better in C++:
I use a struct to manage clients in a message queue, the struct looks like this:
typedef struct _MsgClient {
int handle;
int message_class;
void *callback;
void *private_data;
int priority;
} MsgClient;
All of these being POD entities.
Now, I have an array of these structs where I store my clients (I use an array for memory constraints, I have to limit fragmentation). So in my class I have something like this:
class Foo
{
private:
MsgClient _clients[32];
public:
Foo()
{
memset(_clients, 0x0, sizeof(_clients));
}
}
Now, I read here and there on SO that using memset is bad in C++, and that I'd rather use a constructor for my structure.
I figured something like this:
typedef struct _MsgClient {
int handle;
int message_class;
void *callback;
void *private_data;
int priority;
// struct constructor
_MsgClient(): handle(0), message_class(0), callback(NULL), private_data(NULL), priority(0) {};
} MsgClient;
...would eliminate the need of the memset. But my fear is that when foo is initialized, the struct constructor will be called 32 times, instead of optimizing it as a simple zero out of the memory taken by the array.
What's your opinion on this?
I just found this: Can a member struct be zero-init from the constructor initializer list without calling memset? , is it appropriate in my case (which is different: I have an array, not a single instance of the structure)?
Also, according to this post, adding a constructor to my structure will automatically convert it into a non-POD structure, is it right?
On a conforming implementation, it's perfectly valid to value-initialize an array in the constructor initializer list with an empty member initializer. For your array members, this will have the effect of zero-initializing the members of each array element.
The compiler should be able to make this very efficient and there's no need for you to add a constructor to your struct.
E.g.
Foo() : _clients() {}
You can you memset freely even in C++, as long as you understand what you are doing.
About the performance - the only way to see which way is really faster is to build your program in release configuration, and then see in the disassembler the code generated.
Using memset sounds somewhat faster than per-object initialization. However there's a chance the compiler will generated the same code.
I am searching a 2D matrix (or bitmap) class which is flexible but also fast element access. The contents A flexible class should allow you to choose dimensions during runtime, and would look something like this (simplified):
class Matrix
{
public:
Matrix(int w, int h) :
data(new int[x*y]), width(w) {}
void SetElement(int x, int y, int val)
{
data[x+y*width] = val;
}
// ...
private: // symbols
int width;
int* data;
};
A faster often proposed solution using templates is (simplified):
template <int W, int H>
class TMatrix {
TMatrix() data(new int[W*H]) {}
void SetElement(int x, int y, int val)
{
data[x+y*W] = val;
}
private:
int* data;
};
This is faster as the width can be "inlined" in the code. The first solution does not do this. However this is not very flexible anymore, as you can't change the size anymore at runtime.
So my question is:
Is there a possibility to tell the compiler to generate faster code (like when using the template solution), when the size in the code is fixed and generate flexible code when its runtime dependend?
I tried to achieve this by writing "const" where ever possible. I tried it with gcc and VS2005, but no success. This kind of optimization would be useful for many other similar cases.
I'd just go with the first version, myself.
But, if you really want to try to get the best of both worlds, you could have a Matrix class which holds a pointer to a polymorphic implementation type. For common sizes (say up to 4x4), you could point at template instantiations, and for larger you could point at an implementation that handled the general MxN case.
Having said all that, I think all the indirection & virtual calls would negate any performance improvement that might come from the templates. I don't think you can have your cake & eat it too, in this case.
If you're always dealing with data who's size is known at compile time (graphics/geometry vectors for example), you're better off with the template version (possibly storing the data in statically sized (non-heap allocated) arrays). If you need a general capability for arbitrary data, use the dynamic version instead.
Of course your needs may differ, but I'd skip the automatic generation and just go with a plain&simple set of "fixed" versions. E.g. Vector3, Vector4, Matrix3x3, Matrix3x4, and Matrix4x4. I suppose you could derive all of those from the templated version, but it won't make any particular performance difference.
Is there any particular reason why you want to be able to change the dimensions at runtime? Because I would suggest that just copying from one to the other wouldn't be terribly costly for the (what I suspect to be rare) instances when the change needs to occur.
Finally- something that I've seen done is to have named element access as well as the array, but you can only do that with "hard coded" types. Something like:
class Vector3
{
public:
// other stuff...
union
{
struct { float x, y, z; };
float m[3];
};
};
(that may not be entirely legal C++, hack to suit your compiler.)
Oh, even the templated version doesn't need to use new. Just declare the data as float data[W*H]; Getting it out of the heap will be a bigger performance boost than "optimizing out" a bit of math.
Not so much a complete answer, but some info that may help (if you're not already aware of these): Both OpenCV and Boost (uBLAS) have very good (fast/complete/full-featured) matrix implementations. I've not looked inside them to see how they set/get elements or resize after instantiation though.