Is there a syntax to initialize DataItem dh.size element to sizeof(DataItem)? The code below uses constructor and relying on compiler to optimize things to constant values. Not the perfect solution... Is there a syntax to initialize nested structs?
struct DataHeader_t {
int sz = 0;
int type = 0;
};
struct DataItem {
DataItem() {dh.sz = sizeof(DataItem);}
DataHeader_t dh;
float data1 = 0;
float data2 = 0;
...
};
Not the perfect solution... Is there a syntax to initialize nested structs?
Yes, that structure is called constructor, and you're already using it.
Related
I have the below structures in my C++ code.
struct XYZ {
double x;
double y;
double z;
};
struct Data {
XYZ xyz_point;
double item_1;
double item_2;
double item_3;
};
In my code I create a vector of structure Data.
std::vector<Data> data_vector;
for (i = 0; i < 5; i++) {
Data data_point_1;
data_point_1.xyz_point.x = 10.0;
data_point_1.xyz_point.y = 11.0;
data_point_1.xyz_point.z = 12.0;
data_point_1.item_1 = 13.0;
data_point_1.item_2 = 14.0;
data_point_1.item_3 = 15.0;
data_vector.push_back(data_point_1);
}
Code build successful without any errors, however during the CPP_Check I get the below warnings/error. data_point_1 does not have the field x, y and z.
[test.cc:122]: (error: uninitStructMember) Uninitialized struct member: data_point_1.x
[test.cc:122]: (error: uninitStructMember) Uninitialized struct member: data_point_1.y
[test.cc:122]: (error: uninitStructMember) Uninitialized struct member: data_point_1.z
Could you please help me to resolve this.
Thank you,
push_back requires a default constructor. The compiler is able to supply that, but it doesn't initialise the doubles.
CPP_Check is spotting that.
One fix is to use emplace_back instead with the initialiser-list syntax. That doesn't require a default constructor. Another option is to supply a default constructor that initialises the members.
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();
}
How can I initialize struct array with parameters in constructor?
Now I have this code:
struct roundMatrix {
private:
int **matrix;
public:
roundMatrix(int teamsNumber) {
matrix = new int*[teamsNumber];
for(int i=0;i<teamsNumber;i++) {
matrix[i] = new int[teamsNumber];
}
}
int addPartners(int first, int second) {
if(matrix[first][second] == -1 && matrix[second][first] == -1) {
matrix[first][second] = 0;
matrix[second][first] = 0;
}
else {
return -1;
}
return 0;
}
};
...
Then I need to inintialize array of roundMatrix with parameter:
roundMatrix rounds[roundsNumber](teamsNumber);
And I got an error:
variable-sized object 'rounds' may not be initialized
One more question. How can I initialize vector with struct and constructor paramaters?
You cannot initialize array in that way. It should be written as:
roundMatrix rounds[roundsNumber] = {teamsNumber, teamsNuber, ...);
Alternatively you need to implement a default constructor for roundMatrix class that will automatically initialize the items in your array.
At first your struct is class. struct should be used in C++ without methods, inheritance, encapsulation and other class's stuff as same as in standart C code.
Next, class names should be in upper camel case: first character of the name should be in uppercase and each new word in the name should begin from uppercase character. By the way your corporate code conventions may override this default convention which uses almost everywhere in C++ code.
And last: in case you have an array of objects of this class you can't call constructor for each object of this class during initialization. You can do something like that:
roundMatrix *rounds = new roundMatrix[roundsNumber];
for(i = 0; i < roundsNumber; i++)
rounds[i] = roundMatrix(teamsNumber);
It's easy to create and initialize a struct...
struct S{ int x; bool b; };
S s = {123,false};
But is it possible to use the same trick on an existing object? Or is this a 1-time only thing?
S s = {123,false};
s = {456,true}; //fails
s = S(){456,true}; //fails
Is there a syntax trick... obviously I could do:
S s = {123,false};
S temp={456,true};
s = temp;
But can I remove explicitly declaring the temp variable?
I should add I'm working on VC++ 2008, so no fancy modern C++ stuff is available :(
No. Initialization is a one time occurrence. Initialization occurs only when you create as well as assign some values to the created object at the same time (i.e., in one statement0.
Once the object is created you can only assign new values to it.
In short,
You can't reinitialise anything in C++. You can initialise objects or you can assign them.
Once you understand this fact, you can see that there are number of solutions possible such as
passing the structure members to the constructor & creating the structure object of it
overloading the =operator to do whatever you want
You could add a constructor to your struct and then you could do something like:
struct S
{
S(int x_in, bool b_in): x(x_in), b(b_in) { }
int x;
bool b;
}
S s(123, false);
s = S(456, true);
In c++11 you can:
s = S({456, true});
In C++11, an you can construct a temporary from an initializer list and use it with assignment operator. Thus you can write:
struct S {
int x;
bool b;
};
int main()
{
S s = {42, true};
s = {0, false};
}
I dont think struct would support re initialization by default.
S s = {123,false};
S temp={456,true};
s = temp; //calls the = operator
Maybe you could try overloading the assignment operator
Or you can try creating temp on the fly.
S s = {123,false};
s = S (456,true); // this should work i suppose
I have this code
enum type {NOTHING, SOMETHING, SOMETHINGELSE}
type *x;
At the moment I use x[765] == SOMETHING for example, How would I store other values for example
x[765] == SOMETHINGELSE;
x[765].position == 43.5;
x[765].somevar == 12;
I will apologize for my poor wording within my question im just starting out in C++, I know what I want i'm just not to sure on how to ask it.
Thanks.
It looks as if you're looking for a way to structure 'knowledge'; this is done with a struct or a class:
#include <vector>
struct Info {
enum thingness { nothing, something };
// 'member' variables
thingness howMuch;
int a_counter;
float position;
};
int main(){
Info object;
object.howMuch=Info::something;
object.a_counter=1;
object.position=5.4;
You can group these kinds of objects into a container - typically an std::vector:
// a container of InterestingValues
std::vector<Info> container(300);
container[299].howMuch=Info::nothing;
container[299].a_counter=4;
container[299].position = 3.3;
// or assign rightaway:
container[2] = object;
}
You will have to make yourself a more complex type:
struct type
{
enum flag_type
{
NOTHING, SOMETHING, SOMETHINGELSE
} flag;
double position;
int somevar;
};
and later have an array of this new type.
Get yourself a good book to learn from. A list of good books is available here: The Definitive C++ Book Guide and List
In C++, you are asking how to declare an array of structures. Try this:
struct type {
double position;
int somevar;
};
type *x;
x[765].position = 43.5;
x[765].somevar = 12;
An enum is a replaceable label basically for an int. You need to define a struct or a class.
struct type
{
float position ;
};
type var;
var.position = 3.4;
Your type enum would need to be a member of a class, along with the other fields. For example,
class MyType
{
public:
type t;
double position;
int somevar;
};
With an array of MyType instances
MyType *x;
you would then be able to do what you ask expect you would need to do
x[765].t = SOMETHINGELSE;
to assign to the enum.