Initialize POD struct - c++

#include <iostream>
using namespace std;
struct POD
{
int i;
char c;
bool b;
double d;
};
void Func(POD *p) { ... // change the field of POD }
void ModifyPOD(POD &pod)
{
POD tmpPOD = {};
pod = tmpPOD; // first initialize the pod
Func(&pod); // then call an API function that will modify the result of pod
// the document of the API says that the pass-in POD must be initialized first.
}
int main()
{
POD pod;
ModifyPOD(pod);
std::cout << "pod.i: " << pod.i;
std::cout << ", pod.c: " << pod.c;
std::cout << " , pod.b:" << pod.b;
std::cout << " , pod.d:" << pod.d << std::endl;
}
Question> I need to design a function that modify the pass-in variable pod. Is the above function named as ModifyPOD correct? First, I initialize the struct by assigning it(i.e. pod) with the value from a local struct(i.e. tmpPOD). Then, the variable is passed to Func.
I use the local variable to initialize the pod so that I can avoid to do the following instead:
pod.i = 0;
pod.c = ' ';
pod.b = false;
pod.d = 0.0;
However, I am not sure whether this practice is legitimate or not.
Thank you

Yes, it is legitimate. I''ll just add that you can do
pod = POD();
Func(&pod);
in the ModifyPod() function which is equivalent and simpler.

Related

How to safely copy a global object to a pointer

I have a header class that contains a declaration of a inline variable that I'm using as a global variable. I want to make a copy of this variable every time I call a function.
globalitems.h
#ifndef GLOBALVAR_H
#define GLOBALVAR_H
struct Data {
int a;
Data(int ca) {
a = ca;
}
};
inline Data globaldata(3);
#endif
Otherclass.h
#include "globalitems.h"
void createPointerCopy() {
Data* tempPointer = &globaldata;
tempPointer->a = 30;
std::cout << tempPointer->a << std::endl;
std::cout << globaldata.a << std::endl;
}
int main() {
createPointerCopy();
return 0;
}
outputs
30
30
Whereas my desired output is
30
3
How can I make it so that createCopy() safely creates a copy of the globaldata object?
If I understand you well, what you want is not getting a pointer to your global object but you want to create a copy, that is:
void createPointerCopy() {
Data temp = globaldata;
temp.a = 30;
std::cout << temp.a << std::endl;
std::cout << globaldata.a << std::endl;
}
So, I think your problem is that both variables point to the same place in memory.
What you really tell compiler to do with:
Data* tempPointer = &globaldata;
is to take address of globaldata and assign it to tempPointer. Thus, by changing fields of tempPointer, you change fields globaldata. Or, in other words, (*tempPointer) becomes an alias to globaldata.
I see two options:
Data tempData = globaldata;
and provide copy constructor if necessary; Or just:
int tempVal = globaldata.a
Additionally, I think you may want to be introduced with Singleton pattern

insertion into unordered_map got lost

I'm having the following code, but after run the code, the result is empty, any ideas why the result is empty? the reference of result in function main was passed to myclass, I thought function addToResult will actually add data to result, and I'm expecting a map key = "test", value = "1": "1". I'm kind of new to c++. Thanks!
#include <iostream>
#include <string>
#include <unordered_map>
using LookUpTable = std::unordered_map<std::string, std::string>;
using DLTable = std::unordered_map<std::string, LookUpTable>;
class MyClass
{
public:
MyClass(DLTable& dltable) {
m_dltable = dltable;
};
void addToResult() {
LookUpTable ee;
ee.emplace("1", "1");
m_dltable.emplace("test", ee);
};
private:
DLTable m_dltable;
};
int main ()
{
DLTable result;
MyClass myclass(result);
myclass.addToResult();
std::cout << "myrecipe contains:" << std::endl;
for (auto& x: result) {
std::cout << x.first << ": "<< std::endl;
for (auto& xx : x.second) {
std::cout << xx.first << ": " << xx.second << std::endl;
}
}
std::cout << std::endl;
return 0;
}
Let' look into simplified example:
int a = 0;
int &b = a;
int c = b;
c = 123;
Will last assignment modify a? Of course not. It does not matter how you pass value to c through reference or not c is completely independent variable that just initialized by a reference.
Your case is the same - m_dltable is separate variable and the fact you initialize it using reference does not change anything. (Your case even worse, you did not initialize it by reference, you assigned to it)
In general your approach is wrong. If you want directly access that variable then just make it public, do not try to create convoluted workarounds on how to access it. If you want incapsulation just create members that allow you to iterate over that container. For example return a const reference to it or have begin() and end() methods that return (const) iterators accordingly.

How to write a constructor for non-named class [duplicate]

Is there a way to declare a constructor or a destructor in an unnamed class? Consider the following
void f()
{
struct {
// some implementation
} inst1, inst2;
// f implementation - usage of instances
}
Follow up question : The instances are ofcourse constructed (and destroyed) as any stack based object. What gets called? Is it a mangled name automatically assigned by the compiler?
The simplest solution is to put a named struct instance as a member in the unnamed one, and put all of the functionality into the named instance. This is probably the only way that is compatible with C++98.
#include <iostream>
#include <cmath>
int main() {
struct {
struct S {
double a;
int b;
S() : a(sqrt(4)), b(42) { std::cout << "constructed" << std::endl; }
~S() { std::cout << "destructed" << std::endl; }
} s;
} instance1, instance2;
std::cout << "body" << std::endl;
}
Everything that follows requires C++11 value initialization support.
To avoid the nesting, the solution for the construction is easy. You should be using C++11 value initialization for all members. You can initialize them with the result of a lambda call, so you can really execute arbitrarily complex code during the initialization.
#include <iostream>
#include <cmath>
int main() {
struct {
double a { sqrt(4) };
int b { []{
std::cout << "constructed" << std::endl;
return 42; }()
};
} instance1, instance2;
}
You can of course shove all the "constructor" code to a separate member:
int b { [this]{ constructor(); return 42; }() };
void constructor() {
std::cout << "constructed" << std::endl;
}
This still doesn't read all that cleanly, and conflates the initialization of b with other things. You could move the constructor call to a helper class, at the cost of the empty class still taking up a bit of space within the unnamed struct (usually one byte if it's the last member).
#include <iostream>
#include <cmath>
struct Construct {
template <typename T> Construct(T* instance) {
instance->constructor();
}
};
int main() {
struct {
double a { sqrt(4) };
int b { 42 };
Construct c { this };
void constructor() {
std::cout << "constructed" << std::endl;
}
} instance1, instance2;
}
Since the instance of c will use some room, we might as well get explicit about it, and get rid of the helper. The below smells of a C++11 idiom, but is a bit verbose due to the return statement.
struct {
double a { sqrt(4) };
int b { 42 };
char constructor { [this]{
std::cout << "constructed" << std::endl;
return char(0);
}() };
}
To get the destructor, you need the helper to store both the pointer to an instance of the wrapped class, and a function pointer to a function that calls the destructor on the instance. Since we only have access to the unnamed struct's type in the helper's constructor, it's there that we have to generate the code that calls the destructor.
#include <iostream>
#include <cmath>
struct ConstructDestruct {
void * m_instance;
void (*m_destructor)(void*);
template <typename T> ConstructDestruct(T* instance) :
m_instance(instance),
m_destructor(+[](void* obj){ static_cast<T*>(obj)->destructor(); })
{
instance->constructor();
}
~ConstructDestruct() {
m_destructor(m_instance);
}
};
int main() {
struct {
double a { sqrt(4) };
int b { 42 };
ConstructDestruct cd { this };
void constructor() {
std::cout << "constructed" << std::endl;
}
void destructor() {
std::cout << "destructed" << std::endl;
}
} instance1, instance2;
std::cout << "body" << std::endl;
}
Now you're certainly complaining about the redundancy of the data stored in the ConstructDestruct instance. The location where the instance is stored is at a fixed offset from the head of the unnamed struct. You can obtain such offset and wrap it in a type (see here). Thus we can get rid of the instance pointer in the ConstructorDestructor:
#include <iostream>
#include <cmath>
#include <cstddef>
template <std::ptrdiff_t> struct MInt {};
struct ConstructDestruct {
void (*m_destructor)(ConstructDestruct*);
template <typename T, std::ptrdiff_t offset>
ConstructDestruct(T* instance, MInt<offset>) :
m_destructor(+[](ConstructDestruct* self){
reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(self) - offset)->destructor();
})
{
instance->constructor();
}
~ConstructDestruct() {
m_destructor(this);
}
};
#define offset_to(member)\
(MInt<offsetof(std::remove_reference<decltype(*this)>::type, member)>())
int main() {
struct {
double a { sqrt(4) };
int b { 42 };
ConstructDestruct cd { this, offset_to(cd) };
void constructor() {
std::cout << "constructed " << std::hex << (void*)this << std::endl;
}
void destructor() {
std::cout << "destructed " << std::hex << (void*)this << std::endl;
}
} instance1, instance2;
std::cout << "body" << std::endl;
}
Unfortunately, it doesn't seem possible to get rid of the function pointer from within ConstructDestruct. This isn't that bad, though, since its size needs to be non-zero. Whatever is stored immediately after the unnamed struct is likely to be aligned to a multiple of a function pointer size anyway, so there may be no overhead from the sizeof(ConstructDestruct) being larger than 1.
You can not declare a constructor or destructor for an unnamed class because the constructor and destructor names need to match the class name. In your example, the unnamed class is local. It has no linkage so neither mangled name is created.
If you are thinking of C++ names, then any class that has objects has to have a destructor whether you create it explicitly or not. So yes, the compiler knows how to assign a name. Whether that naming convention is any of your business, however, probably not.
Actually, you can create a structure or also a namespace without a name. You still need to have names somewhere because at the time you link all of that, the linker needs some kind of a name to make it all work, although in many cases it will be local names that are resolved immediately at compile time--by the assembler.
One way to know of the names assigned by the compiler is to look at the debug strings and see what corresponds to the different addresses that you're interested in. When you compile with -g then you should get all the necessary debug for your debugger to place your current at the right place with the right "names"... (I've see the namespaces without a name it says " namespace", I'm pretty sure structures use the same trick at a higher level.)

C++ Unions in the Memory

I am fiddling with a code like following:
union Data {
int i;
double x;
std::string str;
~Data(){}
};
union Data var = {.x = 31293.932};
std::cout << var.x << "\n";
std::cout << var.str << "\n";
std::cout << var.i << "\n";
As far as I know, the union have some 64 bit thing written after I set x member to some floating point number. Then I want to see corresponding string, asuming I treated those bytes as char. But I am getting segmentation fault when I try to print it as string. Why is that? I initialized the union so I assume var.str must be initialized as well.
str is not constructed. if you must use str you must either provide a constructor for it or construct it via placement new. A full example below
#include <iostream>
#include <vector>
using namespace std;
union Data
{
int i;
double x;
std::string str;
Data() {}
Data(std::string st) : str(st) {}
~Data() {}
};
int main()
{
Data var;
var.x = 31293.932;
new (&var.str) std::string("Hello World!");
std::cout << var.x << "\n";
std::cout << var.str << "\n";
std::cout << var.i << "\n";
//destroy it
var.str.std::string::~string();
}
EDIT:
Just to expand my answer a bit...
MSDN seems to have a n00bie friendly explanation about unions than cppreference. So, check: Unions - MSDN and Unions - cppreference
You should be using char to access the bytes in the union. std::string is not a POD type and can't be used in this way.
Try this instead:
union Data {
int i;
double x;
char bytes[sizeof(double)];
~Data(){}
};
union Data var = {.x = 31293.932};
std::cout << var.x << "\n";
std::cout.write(var.bytes, sizeof(var.bytes));
std::cout << "\n" << var.i << "\n";
The full definition of what a POD type is extensive. In very simple terms it is a basic data type without a explicitly-defined copy constructor, destructor, or virtual methods and does not itself contain any such types if it is an aggregate type (like struct, class, and unions).

type defined in free function, accessible through auto outside. Language Bug or Feature?

Let's define a class inside a free function, and access it outside:
#include <iostream>
auto myFunc(){
class MyType{public: int i = 0; int j = 1;};
return MyType();
}
int main() {
auto my_type = myFunc();
std::cout << my_type.i << " " << my_type.j << "\n";
return 0;
}
It compiles, run as expected:
0 1
The name MyType is properly hidden:
if we replace auto, the following won't compile:
int main() {
MyType my_type = myFunc();
std::cout << my_type.i << " " << my_type.j << "\n";
return 0;
}
What does the standard say about it?
How to prevent it? The following code did not help:
namespace{
auto myFunc(){
class MyType{public: int i = 0; int j = 1;};
return MyType();
}
}
int main() {
auto my_type = myFunc();
std::cout << my_type.i << " " << my_type.j << "\n";
// your code goes here
return 0;
}
The standard doesn't say anything about this specifically, except that — as you've already pointed out — it's the name that has a scope, not the type. Use of auto bypasses the type's name, giving you a way to get at the type regardless of the name's scope.
It's kind of similar to how making a nested class private doesn't mean you can't use instances of it, only that you can't name it outside of the encapsulating class's scope.
I don't see how you'd "prevent" it, nor why you'd want to.