C++ Struct Value Initialization - c++

I was messing around with structs and noticed that of the following two examples, only one worked. Here they are:
struct Test
{
char *name;
int age;
};
Test p1 = { "hi", 5 };
//works
struct Test
{
char *name;
int age;
}p1;
p1 = { "hi", 5 };
//error
How come the first one compiles and the second one doesn't? Isn't p1 an object of Test either way? Thanks.

In the first example you are initializing a struct with two values in a "brace initialization." There is no support in C++ (or C) for assigning to a struct using a brace-enclosed list.
You could, however, create a new struct using brace initialization, then assign it to the old struct (p). C++ (and C) does support assignment of one struct to another of the same type.
For example, in C++11:
p1 = Test{ "hi", 5 };

The following does work with C++11:
(Compile with g++ -std=c++11 init.cpp)
#include <iostream>
struct XXX {
int a;
const char *b;
};
int main() {
XXX x;
x = XXX{1, "abc"};
// or later...
x = XXX{2, "def"};
std::cout << x.b << std::endl;
return 0;
}

Related

why can i put variable name as constructor parameter in c++? [duplicate]

This question already has answers here:
Is it true that a default constructor is synthesized for every class that does not define one?
(6 answers)
Closed 3 months ago.
in following code:
`
#include <iostream>
struct MyStruct {
int i = 1;
};
int main() {
MyStruct(some); // some is actually a variable name, it compiles, is it in the
// c++ standard?
std::cout << some.i << std::endl;
}
`
why can i initialzie MyStruct(some)?
above code compiles and runs
I doubt that the variable "some" in the first code is a variable, it wouldn't run when I try to declare a variable called some.
But your problem with this code...
struct MyStruct {
MyStruct(const int &value) {}
};
int main() {
std::string(s2);
MyStruct(some); // illegal now
std::cout << s2 << std::endl;
}
is that you don't have an identifier for the MyStruct that you are instantiating.
struct MyStruct {
MyStruct(const int &value) {}
};
int main() {
int some = 5;
std::string(s2);
MyStruct myStruct (some); // illegal now
std::cout << s2 << std::endl;
}
Here I placed "myStruct" as the identifier for the "MyStruct". I also declared a variable called "some" to check if it runs that way, which it does.
The way of declaring and defining a variable is very wired. If you want to define std::string and MyStruct, you are supposed to use the following way: std::string s2("initialized value"); MyStruct some. In your second case, MyStruct has defined a constructor so the default constructor in the first case doesn't exist anymore unless you explicitly define it.
So in the second case, if you want to initialize an instance with one argument, the following is a supported way:MyStruct some(10);. This statements call the constructor you write.

What happens if you put a struct within a struct?

struct b;
struct a {
int argx;
int argy;
b structB;
};
struct b {
int argw;
int argz;
a structA;
};
int main() {
a structA;
std::cout >> structA.argx >> std::endl;
// Couldn't you do std::cout >> structA.structB.structA.structB... ;
}
What will happen? Will there be recursive memory usage?
I was wondering this because I was doing something like this in my code.
That's not possible in C and C++. You can't use the struct b in the struct a before it is defined. Even if you use forward declarations you can only use a pointer or reference. You can't create an instance of an incomplete type.
You can't compile this code.
You can create a pointer to an incomplete type instead:
struct b;
struct a {
int argx = 1;
int argy;
b *structB;
};
struct b {
int argw = 2;
int argz;
a *structA;
};
int main() {
a structA;
b structB;
structA.structB = &structB;
structB.structA = &structA;
std::cout >> structA.argx >> '\n';
std::cout >> structA.structB->argw >> '\n';
std::cout >> structA.structB->structA->argx >> '\n';
}
Should be fine. I've used structs in other structs before and never noticed a difference. Then again I wasn't profiling performance.
I wouldn't have both structs include each other though. I feel like that would be bad.
Edit: As #Thomas Sablik pointed out you can't use struct b in a, because it wasn't defined before.
I was talking about using a in b not the other way around. (when I've used structs in structs before)

Define all constants as const references?

Is there a best practice to define a constant? Here is a small example:
#include <vector>
struct mystruct {
std::vector<double> data;
mystruct() : data(100000000,0) {};
};
int main(){
mystruct A;
int answer = 42;
const mystruct& use_struct_option_1 = A; // quick
const mystruct use_struct_option_2 = A; // expensive
const int& use_answer_option_1 = answer; // good practice?
const int use_answer_option_2 = answer; // ubiquitous
}
Obviously, initializing use_struct_option_2 that way is expensive because the copy constructor of mystruct is called whereas the way of initializing use_struct_option_1 is quicker.
However, does the same apply to types such as integers?
From the code I've been locking at I can tell that
const int use_answer_option_2 = answer;
is much more common than
const int& use_answer_option_1 = answer;
Which one is preferable?
These do different things. For example, in the int case:
answer = 43;
cout << use_answer_option_1 << '\n'; // 43
cout << use_answer_option_2 << '\n'; // 42
In other words, option 2 makes a copy and option 1 doesn't.
Decide whether you want to make a copy or not (i.e. whether you want to see changes to the original initializer reflected in your reference). The mystruct case is the same.

c++ assigning dynamic struct

I really want to do the following:
(sorry about syntax, I have no idea how this is done)
struct Data {
int var = 5;
} data;
struct Data2 {
var;
} data2;
data2.var = data;
cout << data2.var.var; //prints 5
Basically I want to have a dynamic struct variable in a struct that can be given any struct as value and access it through the mains struct.
Please be nice. I really don't know how to explain it better and I really want to do this and been reading a lot yet haven't found any methods to do this.
Ps.
I DON'T want to do the following:
struct Data {
int var = 0;
} data;
struct Data2 {
data;
} data2;
I want it to be dynamic, that is, that I can change it any time during the program. Thank you.
Conceptually, you may (?) be asking about references:
#include <iostream>
int main() {
int x = 10;
int & xref = x;
std::cout << xref << "\n";
x = 20;
std::cout << xref << "\n";
}
That will print:
10
20
Underlying a reference is essentially a pointer, but it is one which can never be null...and notationally you don't have to "dereference" it. Were you using pointers, the above would look like:
#include <iostream>
int main() {
int x = 10;
int * xptr = &x;
std::cout << *xptr << "\n";
x = 20;
std::cout << *xptr << "\n";
}
Here they are applied to your example with minimal changes:
#include <iostream>
struct Data {
int var;
};
struct Data2 {
Data & var;
};
int main()
{
Data data = {5};
Data2 data2 {data};
std::cout << data2.var.var << "\n";
data.var = 10;
std::cout << data2.var.var << "\n";
return 0;
}
Odds are "this isn't what you actually want" (you shouldn't usually be exposing member variables, much less member variables that are references to other variables). And they shouldn't be all named var. Etc.
Still, references are an integral part of the language and worth learning about.
(Note: for brevity, you may omit the return 0;...only from main. That's assumed, and legal in the standard; and you may omit its arguments. But you must return an int.)
You can use void pointer like this:
#include <iostream>
using namespace std;
struct Data
{
int var;
}data;
struct Data2
{
void *var;
}data2;
int main()
{
data.var = 5;
data2.var = &data;
cout<<((Data *)data2.var)->var<<endl;
return 0;
}
But it is not safe because somtimes you can't make sure that other struct has member called var which may cause unexpected result.
Basically I want to have a dynamic struct variable in a struct that
can be given any struct as value and access it through the mains
struct.
You can emulate the effect of dynamic typing by using polymorphism. The following is a test example for your case.
#include <iostream>
using namespace std;
struct BaseDataStruct
{
virtual int get_data() = 0;
};
struct Data : BaseDataStruct
{
int var = 5;
virtual int get_data() { return var;}
} data;
struct Data2 {
BaseDataStruct* var;
} data2;
int main()
{
data2.var = &data;
cout<<data2.var->get_data();
return 0;
}
By using BaseDataStruct as an interface base class for all the structs which Data2::var is expected to point to you can achieve the "dynamic typing" behavior you are trying to get.
Note: I changed the Data2::var a to pointer to avoid object slicing. You will need to jump through many hoops to avoid that if you want to have it by value.
TL/DR: C++ is statically typed, so what you want to do is against the spirit of thr language. However, if you really have to you can use void* in C and boost::any in C++
Now a bit more about void* (to know more about boost::any refer to its documentation).
void* is a pointer that holds a raw address in memory. This value beyond this address could be everything: float, int or your struct. Here is the usage example.
struct Data {
int var = 5;
};
struct Data2 {
void* var;
};
int main() {
Data data;
Data2 data2;
data2.var = (void*)(&data);
cout << ((struct Data*)data2.var)->var << endl;
}
If the concept of pointers is new for you you can read about it here. Void pointers are explained there as well.

Define struct array in function

The code:
int i;
struct st
{
int m;
}st_t[2];
void foo()
{
i = 4;
st_t[2] =
{
{10},{20}
}; // it's wrong !!!! but I don't know how to do.
}
int main()
{
foo();
cout<<i<<endl; // will output 4;
cout<<st_t[0].m<<endl; // this should output 10
cout<<st_t[1].m<<endl; // this should output 20
return 0;
}
Is it possible to define a struct array in a function? If it is, then how to do this?
Thanks in advance.
PS:
Sorry my English is not good. I am making a Tetris game, it have a Shape class, I declared a shape struct array in Shape.h, then I assign to the struct array in Shape constructor function in Shape.cpp. Is it right? or how to assign to the struct array so I can use it in another function?
You can initialize an array in the place where it's defined. I.e. either move the definition into the function, or move the initialization out of the function:
struct st
{
int m;
}
st_t[2] = {{10},{20}};
Instead of the direct assignment of values, you can initialize a temporary variable and copy this variable to your global variable:
Delete:
...
st_t[2] = {
{10},{20}
};
...
and add:
...
st tmp[2] = { {10}, {20} };
memcpy(st_t, tmp, sizeof st_t);
...
Addendum:
If it doesn't work for you, there might be another error in your code. From your example:
#include <iostream>
#include <memory.h>
using namespace std;
int i;
struct st { int m; } st_t[2];
void foo()
{
i = 4;
st tmp[2] = { {10}, {20} };
memcpy(st_t, tmp, sizeof st_t); // use: const_addr instead of &const_addr
}
int main()
{
foo();
cout << i << endl; // will output 4;
cout << st_t[0].m << endl; // this should output 10
cout << st_t[1].m << endl; // this should output 20
return 0;
}
all works fine as expected.
If you want to define an array in the function (as your question title and text implies), then add the type specifier st to the definition:
st st_t[2] =
{
{10},{20}
};
However, this will be a separate array to the global one, and so the output from main() won't match what your comments say should happen. If you actually want to assign to the global array, then:
st_t[0].m = 10;
st_t[1].m = 20;
or, in C++11, you can use similar syntax to your example if you replace the plain array with std::array:
std::array<st, 2> st_t;
void foo() {
// Note the extra braces - std::array is an aggregate containing an array
st_t =
{{
{10},{20}
}};
}
If you only want the variable at function scope then
void foo() {
struct {
int m;
} st_t = { {10}, {20} };
// do something
}