"memcopy" style construction of an object in C++ - c++

In certain embedded situations, memory needs to be moved with memcopy style functions (such as from external memory, or using closed API calls).
When such a C++ object needs to be moved this way, however it doesn't have a default constructor, you can't do something like this, :
class Object {
//local data
public:
Object(/* not a default constructor */){}
}
//elsewhere:
Object o; //compiler will complain here...
memcpy_like_function(src_address, &o, sizeof(o));
because Object doesn't have a default constructor, and thus the compiler will complain about creating Object o.
Some notes from things that have shown up in the comments:
memcpy_like_function is like memcpy, it isn't actually memcpy. The src_address isn't a pointer to an address I can reach, or an int representing a pointer to an address I can reach. It is an int representing an address in a memory space I can't reach. The only way for me to access this memory space is with this function.
Object doesn't have a default constructor, has no virtual functions, is neither inherited from, nor inherits anything. Object is trivially copyable.
What is the correct way to deal with creating such an object in this situation, without putting it on the heap? Preferably, I would like to get a stack allocated object that will behave correctly with scope and destructors. For the purposes of this question, Object is not inheriting from anything.

This seems like a horribly bad idea, but assuming that your memcpy_like_function actually works, then you can just add a constructor to Object
class Object {
//local data
public:
Object(void* src_address)
{
memcpy_like_function(src_address, this, sizeof(*this));
}
};
//elsewhere:
Object o(src_address);

because Object doesn't have a default constructor
When Object doesn't have a default constructor,
//Object o;//NG
there is no way to construct Object unless call another ctor or factory function. Because of that, you cannot call memcpy-like function.
When you have way to construct Object, to use memcpy-like function, Object class must grantee that it is trivially copyable class and standard-layout class(not equal to POD class).
trivial class : trivially copyable class && has no default user-defined constructor
POD class : trivial class && standard-layout class

You cannot safely copy an object using a memcpy-like function unless the object is a POD type. If the object is a POD type, you should be able to use:
char destination[sizeof(Object)];
memcpy_like_function(src_address, destination, sizeof(destination));
Object* ptr = reinterpret_cast<Object*>(destination);
My gut-feel says that that should work under all compilers for POD types. Whether it is cause for undefined behavior under some rules of the standard, I am not sure.
If that is cause for undefined behavior under some rules of the standard, you won't be able to save a POD-type to a binary file and read it from the binary file in a standards compliant manner. They rely on the bit-pattern written to a file and read from a file to represent the object.
The following program produces the expected result under g++.
#include <iostream>
#include <cstring>
struct Object
{
int i;
double d;
Object(int ii, double dd) : i(ii), d(dd) {}
};
int main()
{
Object o1(10, 20.34);
char dest[sizeof(Object)];
memcpy(dest, &o1, sizeof(dest));
Object* ptr = reinterpret_cast<Object*>(dest);
std::cout << o1.i << ", " << o1.d << std::endl;
std::cout << ptr->i << ", " << ptr->d << std::endl;
}
Update, in response to OP's comments
The following program works as expected under g++.
#include <iostream>
#include <cstring>
struct Object
{
int i;
double d;
Object(int ii, double dd) : i(ii), d(dd) {}
};
Object testFunction(Object o1)
{
char dest[sizeof(Object)];
memcpy(dest, &o1, sizeof(dest));
Object* ptr = reinterpret_cast<Object*>(dest);
return *ptr;
}
int main()
{
Object o1(10, 20.34);
Object o2 = testFunction(o1);
std::cout << o1.i << ", " << o1.d << std::endl;
std::cout << o2.i << ", " << o2.d << std::endl;
o2.i = 25;
o2.d = 39.65;
std::cout << o2.i << ", " << o2.d << std::endl;
}

What you could do is simply use an array of bytes, then cast.
Note: what you are doing is not really good C++ practice, typically you should use assignment operators or copy constructors, and you should stick to the safer C++ casts rather than a brute-force C-style cast.
Anyway, that being said, this code will work:
class Object {
int i;
public:
Object(int i) : i(i) {}
void foo() const {
std::cout << i << std::endl;
}
};
void bla() {
Object one(1);
char *bytes = new char[sizeof(Object)];
memcpy(bytes, &one, sizeof(Object));
Object &anotherOne = (Object &) *bytes;
anotherOne.foo();
const Object &oneMore = (Object) *bytes;
oneMore.foo();
Object *oneMoreTime = (Object *) bytes;
oneMoreTime->foo();
delete[] bytes;
}
The output is:
1
1
1
In summary, you need to allocate a region of memory on the stack or the heap that will become the Object instance.

Related

how Objects in C++ stored? in heap or stack?

#include <string>
#include <iostream>
class Type {
public:
int x;
Type(int a)
{
x = a;
}
Type(const Type& type1)
{
std::cout << "copy" << std::endl;
}
};
Type Func()
{
Type s(1);
std::cout << &s << std::endl;
return s;
}
int main()
{
Type c = Func();
std::cout << &c << std::endl;
std::cout << c.x << std::endl;
system("pause");
}
C++ allocate memory for object in heap or stack? In Func, suppose "s" is allocated in stack, then why it don't be deconstructed? Why can i stiil call it in main(). I am very confused.
By default, objects are are stored in the stack (unless their implementation has a dynamic allocator, e.g. a map). If you have your own class and instanciate it, it will live in the stack. However, this is not recommended since the stack ougth to be considered a precious and scarce resource. If you were to have a heavy object, or many light objects, it is better to allocate them dynamically.
In modern C++ versions, we have what is called move semantics and move constructors (which can be automatically generated by the compiler). Basically, the compiler optimizes your code. In this case, it would be inefficient to copy the object s to c when s is going to be destroyed anyway. What the move constructor does is basically steal the data from s and give it directly to c (in this case, just using c as an alias for the memory location in which s is stored).

Copy constructor and dynamic memory

I am a beginner in programming and I am learning about copy constructors. From different sources I can see that copy constructors are useful if I want to "deep copy" a class object so the new object's pointer members will point to new memory locations.
My question is, what is the advantage of defining the copy constructor as I do in class CopyCat in my example, if I get the same result with an empty copy constructor (as in class EmptyCat)?
My second question is, why do class Cat and class EmptyCat work differently? The only difference between them is that I define an empty copy constructor in EmptyCat. But as I run the program I can see that in EmptyCat after the copying the pointer member points to a new location while in class Cat it works as a shallow copy.
#include "iostream"
class Cat
{
public:
void GetMem() { std::cout << itsAge << "\n"; }
private:
int * itsAge = new int;
};
class EmptyCat
{
public:
EmptyCat() {}
~EmptyCat() {}
EmptyCat(EmptyCat&obj) {}
void GetMem() { std::cout << itsAge << "\n"; }
private:
int * itsAge = new int;
};
class CopyCat
{
public:
CopyCat() {}
~CopyCat() {}
CopyCat(CopyCat&obj);
int GetAge() { return *itsAge; }
void GetMem() { std::cout << itsAge << "\n"; }
private:
int * itsAge = new int;
};
CopyCat::CopyCat(CopyCat & obj)
{
itsAge = new int;
*itsAge = obj.GetAge();
}
int main()
{
Cat Garfield;
Cat Kitty(Garfield);
std::cout << "Memory addresses for the objects' <itsAge> member:" << std::endl;
std::cout << "Garfield and Kitty (Class Cat):" << std::endl;
Garfield.GetMem();
Kitty.GetMem();
EmptyCat Meow;
EmptyCat Purr(Meow);
std::cout << std::endl << "Meow and Purr (Class EmptyCat):" << std::endl;
Meow.GetMem();
Purr.GetMem();
CopyCat Fluffy;
CopyCat Felix(Fluffy);
std::cout << std::endl << "Fluffy and Felix (Class CopyCat):" << std::endl;
Fluffy.GetMem();
Felix.GetMem();
system("pause");
return 0;
}
If I run the program I get this:
Memory addresses for the objects' <itsAge> member:
Garfield and Kitty (Class Cat):
00BBDA60
00BBDA60
Meow and Purr (Class EmptyCat):
00BB46A0
00BB8280
Fluffy and Felix (Class CopyCat):
00BB82B0
00BBE8A0
Press any key to continue . . .
Deep copying and shallow copying is rather a C concept, where you have only structures and raw pointers. A pointer can be owned, in which case the copy must be deep, or it can be shared, in which case the copy is shallow (and you have to be careful about freeing it if it's allocated with malloc).
In C++, new is now effectively deprecated. We have unique pointers, which are "owning pointers" and "shared pointers". However pointers are relatively rare. Array members of classes are std::vectors, string members are std::strings. And copies are automatically deep, (You use a reference if you want a shallow copy).
Pointers are held back for relatively unusual situations, like trees and graphs.
My question is, what is the advantage of defining the copy constructor as I do in class CopyCat in my example, if I get the same result with an empty copy constructor (as in class EmptyCat)?
You don't get the same result. CopyCat allocates new memory and copies the value from the old class. The EmptyCat just allocates new memory, but does not copy the value.
My second question is, why do class Cat and class EmptyCat work differently? The only difference between them is that I define an empty copy constructor in EmptyCat. But as I run the program I can see that in EmptyCat after the copying the pointer member points to a new location while in class Cat it works as a shallow copy.
In Cat you haven't declared a copy constructor, so the compiler will generate one when needed. The default copy constructor does a member-wise copy from the original. In your case, this will copy the pointer (so that it stores the same address as the original).
In the EmptyCat you have a user defined copy constructor. But as that one doesn't handle the pointer member, its default value will be used.
int * itsAge = new int;
This is what allocates a new int and gets you a different pointer value.
You are not getting the same behavior with and without an empty copy constructor. EmptyCat(EmptyCat& obj) { } does absolutely nothing.
CopyCat(CopyCat& obj) {
itsAge = new int;
*itsAge = obj.GetAge();
}
dynamically allocates a new int and assigns to it a value from the obj.

Why doesn't std::unique_ptr have an aliasing constructor like std::shared_ptr has?

I've just discovered std::shared_ptr's "aliasing constructor" and find myself asking "why doesn't std::unique_ptr have an corresponding one?
That is, if you want to allocate a Foo so that you can pass its Bar member to a function that should entirely manage the lifetime of the Foo, wouldn't it be nice to be able to do so?
#include <memory>
struct B {}
struct A {
B b;
}
void f(std::unique_ptr<B> b);
std::unique_ptr<A> a = std::make_unique<A>();
std::unique_ptr<B> b { std::move(a), &(a->b) }; // a now invalid.
f(std::move(b)); // f now responsible for deleting the A.
This works with std::shared_ptr ( http://ideone.com/pDK1bc )
#include <iostream>
#include <memory>
#include <string>
struct B {
std::string s;
};
struct A {
B b;
A(std::string s) : b{s} {};
~A() { std::cout << "A deleted." << std::endl; }
};
void f(std::shared_ptr<B> b) {
std::cout << "in f, b->s = " << b->s << " (use_count=" << b.use_count() << ")" << std::endl;
}
int main() {
std::shared_ptr<A> a = std::make_shared<A>("hello");
std::shared_ptr<B> b { a, &(a->b) };
a.reset(); // a now invalid.
std::cout << "before f, b->s = " << b->s << " (use_count=" << b.use_count() << ")" << std::endl;
f(std::move(b)); // f now responsible for deleting the A.
std::cout << "after f" << std::endl;
return 0;
}
outputs the expected
before f, b->s = hello (use_count=1)
in f, b->s = hello (use_count=1)
A deleted.
after f
Is there a logical reason why such a thing wasn't included? And/or, is it a bad idea to emulate it with a unique_ptr<B> with a custom deleter that deletes the A?
I believe the “problem” is that, unlike std::shared_ptr, std::unique_ptr's deleter is not type-erased. The default deleter of std::unique_ptr<T> (which has zero size, encoded into the type itself as a barely visible default type parameter) is simply [](T * p){ delete p; }. But it is clear that a std::unique_ptr<B> that was created via std::make_unique<B> and one that was made by pointing to a B member of an A object cannot have the same deleter. The deleter for the latter case would have to do some pointer arithmetic to obtain the original A * pointer back. Those two deleters could only have the same type if both would store an offset or an internal pointer to the original object. And that would no longer have zero size. std::unique_ptr was designed to have zero overhead compared to doing new and delete manually, which is a Good Thing. I don't see any immediate drawbacks from using your own deleters that store that additional pointer, though I'd still have to come across a use-case where I'd find this useful.
shared_ptr has reference counting overhead. In its reference counting block it also stores an explicit deleter (because if you are storing on the heap, what is a few more bytes?)
This is also why a shared_ptr to a base type can remember to delete derived types without a virtual dtor.
unique_ptr, on the other hand, stores its deleter in the instance, and the default deleter is stateless -- 0 bytes used. This makes unique_ptr zero overhead over a raw pointer in terms of memory usage.
A stateless deleter cannot remember to delete something else.
You can add a stateful deleter to unique_ptr that supports aliasing, but then you'll have to alias manually. One of the constructors takes both a pointer and a deleter.

How to avoid big memory allocation with std::make_shared

Let's say that I have some arbitrary class, A:
class A {
//... stuff
};
I want to call into an external API that takes in a shared pointer to some type, like so (I cannot change this interface):
//...much later
void foo(std::shared_ptr<A> _a){
//operate on _a as a shared_ptr
}
However, in the (legacy) code I'm working with, the class A instance I'm working with is allocated on the stack (which I cannot get around):
A a;
//...some stuff on a
//Now time to call foo
On top of this, an instance of class A is quite large, on the order of 1 GB per instance.
I know I could call
foo(std::make_shared<A> a);
but that would allocate memory for a copy of A, which I would really like to avoid.
Question
Is there a way to hack together some call to std::make_shared (possibly with move semantics) so that I am not forced to allocate memory for another instance of class A?
I've tried something like this:
foo(std::make_shared<A>(std::move(a)));
But from what I can tell, a new instance of A is still created.
Example code
#include <iostream>
#include <memory>
using namespace std;
class A{
public:
A(int _var=42) : var(_var){cout << "Default" << endl;}
A(const A& _rhs) : var(_rhs.var){cout << "Copy" << endl;}
A(A&& _rhs) : var(std::move(_rhs.var)){cout << "Move" << endl;}
int var;
};
void foo(std::shared_ptr<A> _a){
_a->var = 43;
cout << _a->var << endl;
}
int main() {
A a;
cout << a.var << endl;
foo(std::make_shared<A>(std::move(a)));
cout << a.var << endl;
a.var = 44;
foo(std::make_shared<A>(std::move(a)));
cout << a.var << endl;
return 0;
}
Output:
Default 42 Move 43 42 Move 43 44
This is possible with the shared_ptr constructor that allows for an "empty instance with non-null stored pointer":
A x;
std::shared_ptr<A> i_dont_own(std::shared_ptr<A>(), &x);
(It's "overload (8)" on the cppreference documentation.)
If you know that shared pointer you pass to foo() will not get stored, copied etc, ie will not outlive your object you can make std::shared_ptr pointed to object on the stack with empty deleter:
void emptyDeleter( A * ) {}
A a;
foo( std::shared_ptr<A>( &a, emptyDeleter ) );
Again you need to make sure that shared pointer or it's copy will not outlive the object and well document this hack.
Assuming class A supports move semantics, do this:
std::shared_ptr<A> newA = make_shared<A> (std::move (_a));
Do not use _a anymore, use only newA. You can now pass newA to the function.
If class A does not support move semantics, there is no safe/sane way to do this. Any hack will only happen to work, and may break in the future. If you control enough of the class code, you may be able to add support for move semantics.
But from what I can tell, a new instance of A is still created.
Why do you care? What you're trying to avoid is copying all the data in the instance, and this does that.
The point of move semantics is to move the data from one instance to another without having to do an allocate/copy/free. Of course, this makes the original instance "empty", so don't use that anymore.

const reference public member to private class member - why does it work?

Recently, I found an interesting discussion on how to allow read-only access to private members without obfuscating the design with multiple getters, and one of the suggestions was to do it this way:
#include <iostream>
class A {
public:
A() : _ro_val(_val) {}
void doSomething(int some_val) {
_val = 10*some_val;
}
const int& _ro_val;
private:
int _val;
};
int main() {
A a_instance;
std::cout << a_instance._ro_val << std::endl;
a_instance.doSomething(13);
std::cout << a_instance._ro_val << std::endl;
}
Output:
$ ./a.out
0
130
GotW#66 clearly states that object's lifetime starts
when its constructor completes successfully and returns normally. That is, control reaches the end of the constructor body or an earlier return statement.
If so, we have no guarantee that the _val memeber will have been properly created by the time we execute _ro_val(_val). So how come the above code works? Is it undefined behaviour? Or are primitive types granted some exception to the object's lifetime?
Can anyone point me to some reference which would explain those things?
Before the constructor is called an appropriate amount of memory is reserved for the object on Freestore(if you use new) or on stack if you create object on local storage. This implies that the memory for _val is already allocated by the time you refer it in Member initializer list, Only that this memory is not properly initialized as of yet.
_ro_val(_val)
Makes the reference member _ro_val refer to the memory allocated for _val, which might actually contain anything at this point of time.
There is still an Undefined Behavior in your program because, You should explicitly initialize _val to 0(or some value,you choose)in the constructor body/Member Initializer List.The output 0 in this case is just because you are lucky it might give you some other values since _val is left unInitialized. See the behavior here on gcc 4.3.4 which demonstrates the UB.
But as for the Question, Yes indeed the behavior is Well-Defined.
The object's address does not change.
I.e. it's well-defined.
However, the technique shown is just premature optimization. You don't save programmers' time. And with modern compiler you don't save execution time or machine code size. But you do make the objects un-assignable.
Cheers & hth.,
In my opinion, it is legal (well-defined) to initialize a reference with an uninitialized object. That is legal but standard (well, the latest C++11 draft, paragraph 8.5.3.3) recommends using a valid (fully constructed) object as an initializer:
A reference shall be initialized to refer to a valid object or function.
The next sentence from the same paragraph throws a bit more light at the reference creation:
[Note: in particular, a null reference cannot exist in a well-defined program, because the only way to create such a reference would be to bind it to the “object” obtained by dereferencing a null pointer, which causes undefined behavior.]
I understand that reference creation means binding reference to an object obtained by dereferencing its pointer and that probably explains that the minimal prerequisite for initialization of reference of type T& is having an address of the portion of the memory reserved for the object of type T (reserved, but not yet initialized).
Accessing uninitialized object through its reference can be dangerous.
I wrote a simple test application that demonstrates reference initialization with uninitialized object and consequences of accessing that object through it:
class C
{
public:
int _n;
C() : _n(123)
{
std::cout << "C::C(): _n = " << _n << " ...and blowing up now!" << std::endl;
throw 1;
}
};
class B
{
public:
// pC1- address of the reference is the address of the object it refers
// pC2- address of the object
B(const C* pC1, const C* pC2)
{
std::cout << "B::B(): &_ro_c = " << pC1 << "\n\t&_c = " << pC2 << "\n\t&_ro_c->_n = " << pC1->_n << "\n\t&_c->_n = " << pC2->_n << std::endl;
}
};
class A
{
const C& _ro_c;
B _b;
C _c;
public:
// Initializer list: members are initialized in the order how they are
// declared in class
//
// Initializes reference to _c
//
// Fully constructs object _b; its c-tor accesses uninitialized object
// _c through its reference and its pointer (valid but dangerous!)
//
// construction of _c fails!
A() : _ro_c(_c), _b(&_ro_c, &_c), _c()
{
// never executed
std::cout << "A::A()" << std::endl;
}
};
int main()
{
try
{
A a;
}
catch(...)
{
std::cout << "Failed to create object of type A" << std::endl;
}
return 0;
}
Output:
B::B(): &_ro_c = 001EFD70
&_c = 001EFD70
&_ro_c->_n = -858993460
&_c->_n = -858993460
C::C(): _n = 123 ...and blowing up now!
Failed to create object of type A