This question already has answers here:
Constructor to specify zero-initialization of all builtin members?
(3 answers)
Closed 8 years ago.
What is the best way to make sure the following large struct always has its integers initialized to 0?
struct Statistics {
int num_queries;
int num_respones;
// ... 97 more counters here
int num_queries_filtered;
}
I would like to avoid having to check each place this struct is initialized to make sure it is value initialized with Statistics s(); rather than default initialized with Statistics s;.
Statistics s; // Default initialized by accident here
s.num_queries++; // Oh no, this is a bug because it wasn't initialized to zero
Statistics s2{}; // Correctly value initialized
s2.num_queries++; // Successful
Proposal 1 - Use memset, but this feels like a hack where we take advantage of the value initialization happening to be equivalent to 0 filling the data structure:
struct Statistics {
Statistics() { memset(this, 0, sizeof(*this)); }
// ... counters here
}
Proposal 2 - Use constructor initialization lists, but this is cumbersome and when people add new counters in the future they may forget to zero-initialize them in the constructor:
struct Statistics {
Statistics() : num_queries(0), num_respones(0), /* ... */, num_queries_filtered(0) {}
// ... counters here
}
Proposal 3 - Force the value initialization to take place as follows:
struct StatisticsUnsafe {
// ... counters here
}
struct Statistics : public StatisticsUnsafe {
Statistics() : StatisticsUnsafe() {}
}
What do you feel is the best approach? Do you have other alternatives?
EDIT I want to clarify that in my actual code, each of the counters has a meaningful name, such as "num_queries_received", "num_responses", etc. Which is why I do not opt to use a vector or array of the form "counters[100]"
EDIT2 Changed the example from Statistics s2(); to Statistics s2{};
From C++11, you may also do:
struct Statistics {
int counter1 = 0;
int counter2 = 0;
// ... more counters here
int counter100 = 0;
};
Unless you have a fairly specific reason to do otherwise, your first choice should probably be a std::vector, such as:
std::vector<int> Statistics(100);
This will zero all the contents automatically. You can address an individual counter in the array as something like:
++Statistics[40];
...which will increment the 41st item (the first is Statistics[0]).
If the size if really fixed at 100 (or some other number you know at compile time) you might prefer to use std::array instead:
std::array<int, 100> Statistics;
This is potentially a little faster and usually uses a (little) less memory, but fixes the size (whereas with an std::vector you can use push_back, erase, etc., to add and remove items).
Given the edited question (the objects really aren't array-like) I'd probably consider something a little different, probably something like this:
template <class T>
class inited {
T val;
public:
inited(T val=T()) : val(val) {}
operator T() const { return val; }
operator=(T const &newval) { val = new_val; }
};
struct Statistics {
inited<int> sum;
inited<int> count;
inited<double> mean;
};
Then an inited<T> is always initialized to some value--you can specify a value if you wish, and if you don't specify any, it uses value initialization (which will give zero for arithmetic types, a null pointer for a pointer type, or use the default constructor for types that define one).
Since it defines an operator T and an operator=, you can still assign to/from elements, just about like usual:
Statistics.sum = 100;
Statistics.count = 2;
Statistics.mean = static_cast<double>(Statistics.sum) / Statistics.count;
You might prefer to use a single:
operator T&() { return val; }
Instead though. This supports both reading and writing (as above) but also compound assignment operators (e.g., += and -=).
Have you considered writing an initializer for each data member?
struct Statistics {
typedef int counter_t;
counter_t counter1 = 0;
counter_t counter2 = 0;
// ... more counters here
counter_t counter100 = 0;
};
Note that if you include such initializers, though, the struct is no longer an aggregate, and hence can't be initialized using aggregate initialization via a braced list. Whether that matters or not for this type is hard to say.
Well you certainly can do something like:
struct Statistics {
int counter1 = 0;
int counter2 = 0;
// ... more counters here
int counter100 = 0;
};
This is perfectly valid in c++11. But the question is, do you really need this? Wouldn't it be more convenient to use a vector?
struct Statistics {
std::vector<int> counters = std::vector<int>(100, 0);
};
And if vector is not an option, you can do some magic in constructor:
struct Statistics {
int counter1;
int counter2;
// ... more counters here
int counter100;
Statistics() {
for (int * i : {&counter1, &counter2, ..., &counter100 }) {
*i = 0;
}
}
};
Statistics s;
s.counter2; // now stores 0 or anything you like.
Here is a C-like way:
#include <assert.h>
#include <cstring>
#include <type_traits>
struct Statistics {
int counter1;
int counter2;
int counter3;
int counter4;
// maybe more //
Statistics() {
// checks whether Statistics is standard-layout
// to be sure that memset won't break it
static_assert(
std::is_standard_layout<Statistics>(),
"Someone broke Statistics, can't use memset to zero it.");
// initializes hole Statistics's memory by zeros
memset(this, 0, sizeof(Statistics));
}
};
// Here is a way how to check Statistics
void assert_Statistics() {
Statistics s;
int* ptr = reinterpret_cast<int*>(&s);
int count = sizeof(Statistics) / sizeof(int);
for (int i = 0; i < count; ++i) {
assert(*(ptr++) == 0);
}
}
int main()
{
Statistics s;
assert_Statistics();
}
Related
I have a class foo that manages data using small buffer optimization (SBO).
When size < 16, the data is held locally (in buffer), otherwise it is stored on the heap, with reserved holding the allocated space.
class foo {
static const int sbo_size = 16;
long size = 0;
char *ptr;
union {
char buffer[sbo_size];
long reserved;
};
public:
foo()
{
for (int i = 0; i < sbo_size; ++i)
buffer[i] = 0;
}
void clone(const foo &f)
{
// release 'ptr' if necessary
if (f.size < sbo_size)
{
memcpy(this, &f, sizeof(foo));
ptr = buffer;
} else
{
// handle non-sbo case
}
}
};
Question about clone():
With the SBO case, it may not be clear for the compiler that union::buffer will be used.
is it correct to use memcpy and set ptr accordingly?
If you can use C++17, I would side-step any potential type-punning problems by using std::variant in place of a union.
Although this uses a small amount of storage internally to keep track of the current type it contains, it's probably a win overall as your ptr variable can disappear (although that should be inside your union anyway).
It's also typesafe, which a union is not (because std::get will throw if the variant doesn't contain the desired type) and will keep track of the type of data it contains simply by assigning to it.
The resulting class fragment might look something like this (no doubt this code can be improved):
class foo
{
private:
static const size_t sbo_size = 16;
using small_buf = std::array <char, sbo_size>;
size_t size = 0;
std::variant <small_buf, char *> buf = { };
public:
void clone (const foo &f)
{
char **bufptr = std::get_if <char *> (&buf);
if (bufptr)
delete [] *bufptr;
size = f.size;
if (size < sbo_size)
buf = std::get <small_buf> (f.buf);
else
{
buf = new char [size];
std::memcpy (std::get <char *> (buf), std::get <char *> (f.buf), size);
}
}
};
Notes:
You will see that I've used std::array instead of a C-style array because std:array has lots of nice features that C-style arrays do not
Why clone and not a copy constructor?
if you want foo to have an empty state (after being default constructed, say), then you can look into the strangely named std::monostate.
For raw storage, std::byte is probably to be preferred over char.
Fully worked example here.
Edit: To answer the question as posed, I am no language lawyer but it seems to me that, inside clone, the compiler has no clue what the active member of f might be as it has, in effect, been parachuted in from outer space.
In such circumstances, I would expect compiler writers to play it safe and set the active member of the union to "don't know" until some concrete information comes along. But (and it's a big but), I wouldn't like to bet my shirt on that. It's a complex job and compiler writers do make mistakes.
So, in a spirit of sharing, here's a slightly modified version of your original code which fixes that. I've also moved ptr inside your union since it clearly belongs there:
class foo {
static const int sbo_size = 16;
long size = 0;
union {
std::array <char, sbo_size> buffer; // changing this
char *ptr;
long reserved;
};
public:
foo()
{
for (int i = 0; i < sbo_size; ++i)
buffer[i] = 0;
}
void clone(const foo &f)
{
// release 'ptr' if necessary
if (f.size < sbo_size)
{
buffer = f.buffer; // lets me do this
ptr = buffer.data ();
} else
{
// handle non-sbo case
}
}
};
So you can see, by using std::array for buffer (rather than one of those hacky C-style arrays), you can directly assign to it (rather than having to resort to memcpy) and the compiler will then make that the active member of your union and you should be safe.
In conclusion, the question is actually rather meaningless since one shouldn't (ever) need to write code like that. But no doubt someone will immediately come up with something that proves me wrong.
I have a structure that contains x amount of integers, It is required that every last one of them be non-zero. Here's my structure:
struct thingy_t{
int a, b, c /* and so on */;
bool init();
};
Over time I will be adding many other members to the structure, which makes it an issue if I forget to check if it's non-zero. That's why I wanted to automate it for every member.
In my init function, it attempts to get values for the members, and return false if any of them are 0.
So far I have this:
bool thingy_t::init(){
a = GetValue(/* blah blah */); // Will return 0 if it can't find anything
b = GetValue(/* other blah */);
/* and so on */
// Check if any value is zero
for(int* i = (int*)this
; i < (int*)((char*)this + sizeof(interfaces_t))
; i++){
if(!*i) return false;
}
return true;
}
I am looking for a better way of doing this that would be more readable and more memory safe, as I am playing with fire(pointers) in a way they probably aren't intended.
Also, sorry for the for loop, I tried to make it more readable by wrapping it, but I probably made it worse.
There isn't a natural way to iterate over the struct and check for certain values of the members you have, so the better option for you, in my opinion, should be either make a better design for your task or make sure that you check for incorrect values on each access to that struct.
I'd simple implement the type to contain an array of int or (possibly better) a standard container.
If the number of values is specified at compile time ....
struct thingy_t
{
int x[number];
bool all_non_zero() const;
};
bool thingy_t::all_non_zero() const
{
for (int i = 0; i < number; ++i)
if (!number[i]) return false;
return true;
}
If the number is not specified at compile time, I'd use a standard container
struct thingy_t
{
std::vector<int> x;
thingy_t(std::size_t size) : x(size) {};
bool all_non_zero() const;
};
bool thingy_t::all_non_zero() const
{
for (std::vector<int>::const_iterator it = x.begin(), end = x.end();
it != end number; ++it)
if (!(*it)) return false;
return true;
}
The above works for all versions of C++, but may be simplified in C++11 or later.
bool thingy_t::all_non_zero() const
{
for (const auto &element : x)
if (!element) return false;
return true;
}
Naturally, you will need other functions to actually store values in the array or vector.
The code won't change if the number of integers changes. You will need to somehow track separately the meaning of each element.
I solved my own question while enjoying a nice breakfast.
Here's how I solved it:
struct thingy_t{
union{
struct{
int a, b, c;
}
int arr[3];
}
}
That way I can access variables via. their name and also their index in an array so I can check if each value is non-zero easier (creds: James Root for the array inspiration)
I am just starting out with C++. I have a class ourVector and within that class I have a constructor that is named ourVector() as well and it includes the initializations of variables. I need these variables to reset with every loop in main, but I can't figure out how to call the constructor in main.
class ourVector
ourVector()
{
vectorCap = 20;
vectorSize = 0;
}
In main my class object is called ourVector vectorTest;
I just would like to figure out how to call ourVector() without getting an error so I can place it at the end of my loop in main to clear and re-initialize the variables.
Any help would be greatly appreciated.
Thank you!
Usually when you find yourself doing things like this it's a sign that maybe there's a more semantically appropriate way to structure your code (i.e. make the code structure more closely represent your intent).
In your case, ask yourself why you need to reset the value every time through the loop. It seems like you are just using your object to hold some intermediate data on each iteration through the loop, and you aren't concerned about the values outside of the loop (but if you are, you want something like riderBill's answer). So really, your ourVector instance is only useful within the scope of that loop.
So make your code structure reflect that:
int main () {
...
while (...) { // <- this represents your loop
ourVector v; // <- each time through, 'v' is constructed
... // <- do whatever with 'v' here
} // <- that 'v' goes away when it goes out of scope
...
}
In other words, just declare it in the loop, where it belongs. Semantically this makes sense (it represents how and where you're actually using the object), and it does what you want without modification to your ourVector.
In general, as a beginner's rule of thumb, try to declare variables in the tightest scope possible that still works for your code.
The constructor is only called when instantiating an object; you cannot explicitly call it to reinitialize your variables. But you can call public member setter function(s) from the constructor. Then you can call the setter function(s) again from within your loop.
class ourVector
{ int vectorCap ;
int const defaultVectorCap = 20; // No magic numbers!
int vectorSize ;
int const defaultVectorSize = 0;
int roomToGrow ; // To illustrate a point about setters.
public:
// Constructors
ourVector() // Use this constructor if you don't know the proper initial values
// (you probably always do or never do).
{ setVectorCap (defaultVectorCap );
setVectorSize(defaultVectorSize);
} // End of default constructor
ourVector( int vecCap, int vecSize) // Lining stuff up improves readability
{ setVectorCap (vecCap ); // (e.g. understanding the code and
setVectorSize( vecSize ); // spotting errors easily).
// It has helped me spot and avoid
// bugs and saved me many many hours.
// Horizontal white space is cheap!
// --Not so forvertical white space IMHO.
// Setters
void setVectorCap(int vecCap)
{ vectorCap = vecCap;
// I might need this internally in the class.
// Setters can do more than just set a single value.
roomToGrow = vectorCap - vectorSize;
} // End of setVector w/ parameter
void setVectorSize(int vecSize)
{ vectorSize = vecSize;
roomToGrow = vectorCap - vectorSize; // Ok, redundant code. But I did say
// "As much as practical...."
} // End of setVectorCap w/ parameter
void setVectorSize() // Set to default
{ // Don't just set it here--leads to poor maintainability, i.e. future bugs.
// As much as practical, redundant code should be avoided.
// Call the setter that takes the parameter instead.
setVectorSize(defaultVectorSize);
} // End of setVectorSize for default size
void setVectorCap() // Set to default
{ setVectorCap (defaultVectorCap );
} // End of setVectorCap for default size
}; // End of class ourVector
#include <cstdio>
#include <cstdlib>
#include "ourVector.hpp"
int main(int argc, char *argv[]);
void doSomething(ourVector oV );
int main(int argc, char *argv[])
{ ourVector oV;
// Or, if you want non-default values,
//int mySize = 2;
//int myCap = 30;
//ourVector(mySize, myCap);
for (int i = 0; i<10; i++)
{ // Set fields to original size.
oV.setVectorSize();
oV.setVectorCap ();
// Or
//oV.setVectorSize(mySize);
//oV.setVectorCap (myCap );
// Whatever it is your are doing
// ...
}
// Do whatever with your vector. If you don't need it anymore, you probably should
// have instantiated it inside the for() block (unless the constructor is
// computationally expensive).
doSomething(oV);
return 0;
} // End of main()
void doSomething(ourVector oV) {}
This code works:
class ourVector
{
public:
ourVector() : vectorCap(20), vectorSize(0) { };
ourVector(int c, int s) : vectorCap(c), vectorSize(s) { };
void setVCap(int v)
{
vectorCap = v;
}
void setVSize(int v)
{
vectorSize = v;
}
int getVCap()
{
return vectorCap;
}
int getVSize()
{
return vectorSize;
}
void print()
{
std::cout << vectorCap << ' ' << vectorSize << '\n';
}
private:
int vectorCap;
int vectorSize;
};
int main()
{
ourVector vectorTest(5,5);
vectorTest.print();
vectorTest.setVCap(6);
vectorTest.setVSize(6);
vectorTest.print();
std::cout << vectorTest.getVCap() << ' ' << vectorTest.getVSize() << '\n';
vectorTest = ourVector();
vectorTest.print();
}
The ourVector() : vectorCap(value), vectorSize(value) { }; parts are the initializers. The vectorCap(value) part sets vectorCap to value; the { } section is an empty method, use this to do any calculations and verifications you need. The SetVCap(int) and SetVSize(int) methods can be called to change the values of vectorCap and vectorSize, respectively. getVCap() and getVSize() return the values of vectorCap and vectorSize respectively.
In my example, you do not need to validate the code, so the initializers ourVector() : vectorCap(value), vectorSize(value) { }; work perfectly fine. If you need to validate the input, you may wish to call the assignment functions from the initializer so you only need to implement the validation once, which makes debugging easier. To do this, just replace the constructors with these constructors. Now you need only validate the input in one place:
ourVector()
{
setVCap(20);
setVSize(0);
}
ourVector(int c, int s)
{
setVCap(c);
setVSize(s);
}
#include <iostream>
using namespace std;
class t
{ public:
int health; //its members
int speed;
int power;
void attack() // its methods
{ cout<<"I'm attacking"<<endl;
};
};
int main()
{ t A,B,C,D;
A.power = 100;
B.health = 87;
C.speed = 92;
cout<<"A= "<<A.power<<"B= "<<A.health<<"C= "<<A.speed<<endl; // <---
cout<< "My health is "<<C.health<<" My speed is "<<A.speed<<endl;
cout<<"My power is "<<B.power<<endl;
D.attack();
system("pause");
return 0;}
The output result was ::
A= 100 B= 96 C=6234392 <--- From where these values come
A.health and A.speed are just junk values on the stack because you didn't explicitly set them. If you want to initialize all fields of A to zero, you can use memset:
memset(&A, 0, sizeof(A));
You should create a constructor to initialize those values to some default value in the initializer list.
class t {
public:
t() : health(100),power(100),speed(100) {}
// ...
};
This will guarantee that those values are all set to 100, or some default, or even an input parameter, rather than garbage. It's considered much better design since otherwise the initialization of those values would be handled in the constructor that the compiler generates for you behind the scenes.
Uninitialized memory?
Uninitialized variable won't be zero setted at the creation of the class/struct. You need to manualy do it. Otherwise, you will get whatever_is_in_memory_at_that_time.
In the code below I would like array to be defined as an array of size x when the Class constructor is called. How can I do that?
class Class
{
public:
int array[];
Class(int x) : ??? { }
}
You folks have so overcomplicated this. Of course you can do this in C++. It is fine for him to use a normal array for efficiency. A vector only makes sense if he doesn't know the final size of the array ahead of time, i.e., it needs to grow over time.
If you can know the array size one level higher in the chain, a templated class is the easiest, because there's no dynamic allocation and no chance of memory leaks:
template < int ARRAY_LEN > // you can even set to a default value here of C++'11
class MyClass
{
int array[ARRAY_LEN]; // Don't need to alloc or dealloc in structure! Works like you imagine!
}
// Then you set the length of each object where you declare the object, e.g.
MyClass<1024> instance; // But only works for constant values, i.e. known to compiler
If you can't know the length at the place you declare the object, or if you want to reuse the same object with different lengths, or you must accept an unknown length, then you need to allocate it in your constructor and free it in your destructor... (and in theory always check to make sure it worked...)
class MyClass
{
int *array;
MyClass(int len) { array = calloc(sizeof(int), len); assert(array); }
~MyClass() { free(array); array = NULL; } // DON'T FORGET TO FREE UP SPACE!
}
You can't initialize the size of an array with a non-const dimension that can't be calculated at compile time (at least not in current C++ standard, AFAIK).
I recommend using std::vector<int> instead of array. It provides array like syntax for most of the operations.
Use the new operator:
class Class
{
int* array;
Class(int x) : array(new int[x]) {};
};
I don't think it can be done. At least not the way you want. You can't create a statically sized array (array[]) when the size comes from dynamic information (x).
You'll need to either store a pointer-to-int, and the size, and overload the copy constructor, assignment operator, and destructor to handle it, or use std::vector.
class Class
{
::std::vector<int> array;
Class(int x) : array(x) { }
};
Sorry for necroing this old thread.
There is actually a way to find out the size of the array compile-time. It goes something like this:
#include <cstdlib>
template<typename T>
class Class
{
T* _Buffer;
public:
template<size_t SIZE>
Class(T (&static_array)[SIZE])
{
_Buffer = (T*)malloc(sizeof(T) * SIZE);
memcpy(_Buffer, static_array, sizeof(T) * SIZE);
}
~Class()
{
if(_Buffer)
{
free(_Buffer);
_Buffer = NULL;
}
}
};
int main()
{
int int_array[32];
Class<int> c = Class<int>(int_array);
return 0;
}
Alternatively, if you hate to malloc / new, then you can create a size templated class instead. Though, I wouldn't really recommend it and the syntax is quite ugly.
#include <cstdio>
template<typename T, size_t SIZE>
class Class
{
private:
T _Array[sz];
public:
Class(T (&static_array)[SIZE])
{
memcpy(_Array, static_array, sizeof(T) * SIZE);
}
};
int main()
{
char int_array[32];
Class<char, sizeof(int_array)> c = Class<char, sizeof(int_array)>(int_array);
return 0;
}
Anyways, I hope this was helpful :)
I had the same problem and I solved it this way
class example
{
int *array;
example (int size)
{
array = new int[size];
}
}
Don't you understand there is not need to use vector, if one wants to use arrays it's a matter of efficiency, e.g. less space, no copy time (in such case if handled properly there is not even need to delete the array within a destructor), etc. wichever reasons one has.
the correct answer is: (quoted)
class Class
{
int* array;
Class(int x) : array(new int[x]) {};
};
Do not try to force one to use non optimal alternatives or you'll be confusing unexperienced programmers
Instead of using a raw array, why not use a vector instead.
class SomeType {
vector<int> v;
SomeType(size_t x): v(x) {}
};
Using a vector will give you automatic leak protection in the face of an exception and many other benefits over a raw array.
Like already suggested, vector is a good choice for most cases.
Alternatively, if dynamic memory allocation is to be avoided and the maximum size is known at compile time, a custom allocator can be used together with std::vector or a library like the embedded template library can be used.
See here: https://www.etlcpp.com/home.html
Example class:
#include <etl/vector.h>
class TestDummyClass {
public:
TestDummyClass(size_t vectorSize) {
if(vectorSize < MAX_SIZE) {
testVector.resize(vectorSize);
}
}
private:
static constexpr uint8_t MAX_SIZE = 20;
etl::vector<int, MAX_SIZE> testVector;
uint8_t dummyMember = 0;
};
You can't do it in C++ - use a std::vector instead:
#include <vector>
struct A {
std::vector <int> vec;
A( int size ) : vec( size ) {
}
};
Declare your array as a pointer. You can initialize it in the initializer list later through through new.
Better to use vector for unknown size.
You might want to look at this question as well on variable length arrays.