The boost::aligned_storage data type is useful to me in order to provide aligned storage in a pre-c++11 world. I have a class that contains this storage member:
template <size_t StoreSize>
class RoutineStorage {
enum { ROUTINE_STORAGE_SIZE = StoreSize};
enum { BUFFER_ALIGNMENT_VALUE = 8 };
template <typename TStorageType> TStorageType& getStorageAsType()
{
BOOST_STATIC_ASSERT_MSG(boost::has_trivial_assign<TStorageType>::value &&
boost::has_trivial_copy<TStorageType>::value,
"The storage type must be trvially copyable and assignable to support this classes "
"copy|assign semantics.");
... // Checking and some other code.
return new (_store.address()) TStorageType();
}
private:
typedef boost::aligned_storage<ROUTINE_STORAGE_SIZE, BUFFER_ALIGNMENT_VALUE>
StorageBuffer;
StorageBuffer _store;
}
I would like to provide a copy constructor for this class, but when i look at the implementation of aligned_storage it has a copy constructor listed as private and a comment // noncopyable. There doesn't seem to be an explanation for this in any of the boost pages about this type, so i concluded that they didn't want to handle copying of different possible templated buffer sizes. I suspect that the following will be fine for copying this buffer:
RoutineStorage(const RoutineStorage<StoreSize>& copy)
{
std::memcpy(_store.address(), copy._store.address(), _store.size())
}
Will there be a problem with this? As far as i can tell the aligned_buffer address function will give the start of a continues memory address and size will let me always copy the correct size.
Just copying the buffer like you do in
RoutineStorage(const RoutineStorage<StoreSize>& copy)
{
std::memcpy(_store.address(), copy._store.address(), _store.size())
}
is not enough. Yes, you will have an exact copy, but you don't actually have the object you created in that StorageBuffer. [intro.object]\1 states that
The constructs in a C++ program create, destroy, refer to, access, and manipulate objects. An object is created by a definition ([basic.def]), by a new-expression, when implicitly changing the active member of a union ([class.union]), or when a temporary object is created ([conv.rval], [class.temporary]).
so until you copy the object into store with placement new you don't actually have an object, just storage.
Lets say you are storing a Foo. Originally you would create the Foo in the StorageBuffer like
Foo* f = new(_store.address()) Foo();
So, in the copy constructor you just need to call the copy constructor of Foo and placing that into _store like
RoutineStorage(const RoutineStorage<StoreSize>& copy)
{
f = new(_store.address()) Foo(copy.*f);
}
Related
Below is the simplified version of a class that I am trying to design
class Class {
public:
Class(std::unique_ptr<int>&& ptr): ptr_(std::move(ptr)) {}
private:
// works only if I change to std::shared_ptr or remove const qualifier
const std::unique_ptr<int> ptr_;
};
int main() {
std::unique_ptr<int> ptr = std::make_unique<int>(1);
Class c(std::move(ptr)); // Compiles
// I need to construct a new instance d, but c is not needed anymore,
// anything c owns can be nullified.
Class d(std::move(c)); // Does not compile
return 0;
}
I can not construct an instance d from the instance c due to the following error message:
Copy constructor of 'Class' is implicitly deleted because field 'ptr_'
has a deleted copy constructor
However, if I change the ptr_ member to be of type const std::shared_ptr<int>, then everything works.
Is there a way to have a single constructor for the Class, which would support:
Constructing the class instance directly providing the arguments it needs
Constructing the class instance from another class instance, possibly destroying another instance in the process (i.e. c(std::move(d));
Allowing the class to have a member of type const unique_ptr
?
EDIT: constructing an instance d using std::move(c) also doesn't work:
class.cc:17:23: error: use of deleted function ‘Class::Class(Class&&)’
17 | Class d(std::move(c));
| ^ class.cc:5:7: note: ‘Class::Class(Class&&)’ is implicitly deleted because the default
definition would be ill-formed:
So far two solutions work for me, neither are perfect from readability point of view:
Remove const qualifier:
std::unique_ptr<int> ptr_;
The problem is that this reads as: "ptr_ member might be modified when calling public methods"
Change to shared pointer:
const std::shared_ptr<int> ptr_;
The problem is that this reads as: "we have multiple pointers pointing to the same data"
Any way to improve the design which wouldn't have the problems outlined in (1) and (2)?
Constructing the class instance from another class instance, possibly destroying another instance in the process (i.e. c(std::move(d));
Allowing the class to have a member of type const unique_ptr
This intersection of desires is inherently contradictory.
Moving is a modifying operation. If the object is const, you cannot move from it.
The entire purpose of unique_ptr is that there is one instance in the program which uniquely owns (and will destroy) the object it points to. Therefore, it cannot be copied, because a copy is a non-modifying operation. If it could be copied, then two objects would try to own the same object.
You cannot copy from a unique_ptr. You cannot move from a const object of any kind. Therefore, if your object has a const unique_ptr, it cannot get a pointer from some other instance of that object.
By declaring a member to be a const unique_ptr<T>, you are also declaring that the object can be neither copied nor moved. Those are the consequences of your code choices.
So you're going to have to decide what is more important: the member being const or the ability to copy/move from this object.
Broadly speaking, const members create more problems than they usually solve. If the member is private, then that is usually good enough protection; users with direct access to the class should be able to know what each such function should and should not modify. And if they make a mistake, the code in which that mistake can appear is pretty limited.
I've found out that unique_ptr can point to an already existing object.
For example, I can do this :
class Foo {
public:
Foo(int nb) : nb_(nb) {}
private:
int nb_;
};
int main() {
Foo f1(2);
Foo* ptr1(&f1);
unique_ptr<Foo> s_ptr1(&f1);
return 0;
}
My question is :
If I create a class with unique_ptr< Bar > as data members (where Bar is a class where the copy constructor was deleted) and a constructor that takes pointers as argument, can I prevent the user from passing an already existing object/variable as an argument (in that constructor) (i.e. force him to use the new keyword) ?
Because if he does, I won't be able to guarantee a valide state of my class objects (the user could still modify data members with their address from outside of the class) .. and I can't copy the content of Bar to another memory area.
Example :
class Bar {
public:
Bar(/* arguments */) { /* data members allocation */ }
Bar(Bar const& b) = delete;
/* Other member functions */
private:
/* data members */
};
class Bar_Ptr {
public:
Bar_Ptr(Bar* ptr) {
if (ptr != nullptr) { ptr_ = unique_ptr<Bar> (ptr); }
} /* The user can still pass the address of an already existing Bar ... */
/* Other member functions */
private:
unique_ptr<Bar> ptr_;
};
You can't prevent programmers from doing stupid things. Both std::unique_ptr and std::shared_ptr contain the option to create an instance with an existing ptr. I've even seen cases where a custom deleter is passed in order to prevent deletion. (Shared ptr is more elegant for those cases)
So if you have a pointer, you have to know the ownership of it. This is why I prefer to use std::unique_ptr, std::shared_ptr and std::weak_ptr for the 'owning' pointers, while the raw pointers represent non-owning pointers. If you propagate this to the location where the object is created, most static analyzers can tell you that you have made a mistake.
Therefore, I would rewrite the class Bar_ptr to something like:
class Bar_ptr {
public:
explicit Bar_ptr(std::unique_ptr<Bar> &&bar)
: ptr(std::move(bar)) {}
// ...
}
With this, the API of your class enforces the ownership transfer and it is up to the caller to provide a valid unique_ptr. In other words, you shouldn't worry about passing a pointer which isn't allocated.
No one prevents the caller from writing:
Bar bar{};
Bar_ptr barPtr{std::unique_ptr<Bar>{&bar}};
Though if you have a decent static analyzer or even just a code review I would expect this code from being rejected.
No you can't. You can't stop people from doing stupid stuff. Declare a templated function that returns a new object based on the templated parameter.
I've seen something similar before.
The trick is that you create a function (let's call it make_unique) that takes the object (not pointer, the object, so maybe with an implicit constructor, it can "take" the class constructor arguments) and this function will create and return the unique_ptr. Something like this:
template <class T> std::unique_ptr<T> make_unique(T b);
By the way, you can recommend people to use this function, but no one will force them doing what you recommend...
You cannot stop people from doing the wrong thing. But you can encourage them to do the right thing. Or at least, if they do the wrong thing, make it more obvious.
For example, with Bar, don't let the constructor take naked pointers. Make it take unique_ptrs, either by value or by &&. That way, you force the caller to create those unique_ptrs. You're just moving them into your member variables.
That way, if the caller does the wrong thing, the error is in the caller's code, not yours.
I understand if you wish to pass a vector of MyClass objects and it is a temporary variable, if there is a move constructor defined for MyClass then this will be called, but what happens if you pass a vector of boost::shared_ptr<MyClass> or std::shared_ptr<MyClass>? Does the shared_ptr have a move constructor which then call's MyClass's move constructor?
if there is a move constructor defined for MyClass then this will be called
Usually not. Moving a vector is usually done my transferring ownership of the managed array, leaving the moved-from vector empty. The objects themselves aren't touched. (I think there may be an exception if the two vectors have incompatible allocators, but that's beyond anything I've ever needed to deal with, so I'm not sure about the details there).
Does the shared_ptr have a move constructor which then call's MyClass's move constructor?
No. Again, it has a move constructor which transfers ownership of the MyClass object to the new pointer, leaving the old pointer empty. The object itself is untouched.
Yes, std::shared_ptr<T> has a move constructor, as well as a templated constructor that can move from related shared pointers, but it does not touch the managed object at all. The newly constructed shared pointer shares ownership of the managed object (if there was one), and the moved-from pointer is disengaged ("null").
Example:
struct Base {}; // N.B.: No need for a virtual destructor
struct Derived : Base {};
auto p = std::make_shared<Derived>();
std::shared_ptr<Base> q = std::move(p);
assert(!p);
If you mean moving std::vector<std::shared_ptr<MyClass>>. Then even the move constructor of std::shared_ptr won't be called. Because the move operation is directly done on std::vectorlevel.
For example, a std::vector<T> may be implemented as a pointer to array of T, and a size member. The move constructor for this can be implemented as:
template <typename T>
class vector {
public:
/* ... other members */
vector(vector &&another): _p(another._p), _size(another._size) {
/* Transfer data ownership */
another._p = nullptr;
another._size = 0;
}
private:
T *_p;
size_t _size;
}
You can see in this process, no data member of type T is touched at all.
EDIT: More specially in C++11 Standard: §23.2.1. General container requirements (4) there is a table contains requirements on implementations of general containers, which contains following requirements:
(X is the type of the elements, u is an identifier declaration, rv is rvalue reference, a is a container of type X)
X u(rv)
X u = rv
C++ Standard: These two (move constructors) should have constant time complexity for all standard containers except std::array.
So it's easy to conclude implementations must use a way like I pointed above for move constructors of std::vector since it cannot invoke move constructors of individual elements or the time complexity will become linear time.
a = rv
C++ Standard: All existing elements of a are either move assigned to or destroyed a shall be equal to the value that rv had before this assignment.
This is for move assign operator. This sentence only states that original elements in a should be "properly handled" (either move-assigned in or destroyed). But this is not a strict requirement. IMHO implementations can choose the best suited way.
I also looked at code in Visual C++ 2013 and this is the snippet I found (vector header, starting from line 836):
/* Directly move, like code above */
void _Assign_rv(_Myt&& _Right, true_type)
{ // move from _Right, stealing its contents
this->_Swap_all((_Myt&)_Right);
this->_Myfirst = _Right._Myfirst;
this->_Mylast = _Right._Mylast;
this->_Myend = _Right._Myend;
_Right._Myfirst = pointer();
_Right._Mylast = pointer();
_Right._Myend = pointer();
}
/* Both move assignment operator and move constructor will call this */
void _Assign_rv(_Myt&& _Right, false_type)
{ // move from _Right, possibly moving its contents
if (get_allocator() == _Right.get_allocator())
_Assign_rv(_STD forward<_Myt>(_Right), true_type());
else
_Construct(_STD make_move_iterator(_Right.begin()),
_STD make_move_iterator(_Right.end()));
}
In this code the operation is clear: if both this and right operand have the same allocator, it will directly steal contents without doing anything on individual elements. But if they haven't, then move operations of individual elements will be called. At this time, other answers apply (for std::shared_ptr stuff).
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
What methods are called when we create an object of a class in c++ or what exactly happens when we create an object of a class.
Without additional information, you should assume that one and only one member function of the class itself is called, the constructor.
class CheesePizza {
public:
CheesePizza() {}
};
CheesePizza barely; // will initialize by calling Foo::foo().
There are many cases in which additional functions might be called, for instance if you create a conversion scenario where a temporary object must be created, such as specifying a std::string argument and passing a const char* value.
class DIYPizza {
std::string m_toppings;
public:
DIYPizza(const std::string& toppings) : m_toppings(toppings) {}
};
DIYPizza dinner("all of the toppings");
This has to create a temporary std::string from the const char* argument, "all of the toppings". Then the DIYPizza::DIYPizza(std::string) operator can be passed this temporary (rvalue), and then subsequently we initialize m_str from it which invokes the std::string(const std::string&) copy constructor to initialize m_str.
What essentially gets done is:
// create a std::string object initialized with the c-string.
std::string rvalueString = std::string("all of the toppings");
// now we have a string to pass to DIYPizza's constructor.
DIYPizza dinner(rvalueString);
However - we're still only calling ONE member function of Foo at this point. The only way for more class members to be invoked is by calling them from whichever constructor is invoked.
class DinnerAtHome {
void orderPizza();
void drinkBeer();
void watchTV(); // I was going with something more brazen, but...
public:
DinnerAtHome() {
orderPizza();
drinkBeer();
watchTV();
drinkBeer();
// arrival of pizza is handled elsewhere.
}
};
Now when you construct a new DinnerAtHome, 5 member functions will be invoked: DinnerAtHome::DinnerAtHome() and the four member-function calls it makes.
Note: "new" is not a member function, it is a global operator.
IF the answer was "five" then either the interviewer was using a trick question or you missed some nuance of what was being asked.
Ok I try overkill answer since no once already selected an answer:
When you create an object the constructor is called, this also involves a call to underlying constructors of members objects, if the object inherits from another object you need also to call constructors of base classes
class Foo: public Bar{
std::vector<int> indices; //default constructor for indices is called
public:
Foo(int a):Bar(a){ //you have to call constructor of Bar here
//else compiling error will occur
}
};
Default constructor is called implicitly for objects that has it. When you create something with "new", first memory is allocated then object is constructed on top of that memory (placement new works in a similiar way, but the chunk of memory may be created explicity by the user elsewhere).
Note that in certain cases you don't know order of constructors calls:
CASE 1
Obj1* myobj= new Obj1 ( new Obj2, new Obj3( new Obj4) );
in this case you have no clues if Obj4 is created before or after Obj2 and if Obj3 is created before or after Obj2, simply the compiler will try to choose "an order" (that may vary depending on compiler and platform), also this is a highly unsafe code:
assume you get exception in Obj3 when Obj2 was already created, then Obj3 memory will never get deallocated (in that extreme case you may find usefull tools for those kinds of problems : Hypodermic / Infectorpp )
see also this answer
CASE 2
static/global variables may be initialized in different orders, and you have to rely on specific compiler functions to declare a initialization order
for GCC:
void f __attribute__((constructor (N)));
also note that "Constructor" is not a "method" like others, infact you cannot save constructor in a std::function nor bind it with std::bind. The only way to save a constructor is to wrap it with a factory method.
well that should be 5 "things" as you mentioned in the interview.
Lets assume your class is called CMyClass.
#include "MyClass.h"
/* GLOBAL objects */
static CMyClass g_obj("foo"); // static makes this object global to this file. you can use it
// anywhere in this file. the object resides in the data segment
// (not the heap or the stack). a string object is created prior
// to the constructor call.
int main(void)
{
....
if (theWorldEnds)
{
/* STACK */
CMyClass obj1; // this calls the constructor CMyClass(). It resides on the stack.
// this object will not exist beyond this "if" section
CMyClass obj2("MyName"); // if you have a constructor CMyClass(string&), the compiler
// constructs an object with the string "MyName" before it calls
// your constructor. so the functions called depend on which
// signature of the constructor is called.
/* HEAP */
CMyClass *obj3 = new CMyClass(); // the object resides on the heap. the pointer obj3
// doesn't exist beyond the scope of the "if" section,
// but the object does exist! if you lose the pointer,
// you'll end up with a memory leak. "new" will call
// functions to allocate memory.
}
}
If you are creating a class means you are calling constructor of that class. If constructor is not in your code than compiler will add the default constructor. YOu can override default constructor to perform some task on object creation.
For
Example:
If you are creating a object of type Person
Person* objPerson = new Person();
It means you are calling Person() method(constructor) of that class.
class Person {
public:
Person() {
// ...
}
};
When an object of a class is instantiated : memory required by the object of the class (depending on its data members) is allocated on the heap and a reference to that memory location is stored by the object name. This individual data members at this memory location on the heap may or may not be initialized depending on the constructor called.
When a new object is constructed, the constructor of the class is invoked to initialize non-static member variables of the class (if the class does not have any constructors, compiler assigns a an empty constructor for the class and invokes it). The constructor may invoke other functions (either library or user-defined functions), but that depends on the functions that programmer has invoked inside the constructor. Also, if the class is part of an inheritance hierarchy, appropriate constructor of base classes are called by compiler before the constructor of the class being instantiated (visit here for a brief explanation).
I want to gain a better understanding of how to implement the RAII idiom with my classes, through an example: What the recommended method is for ensuring pointers are free()'d properly in my class?
I have a class which should exist for the duration of the program. In the spirit of RAII and because I need to pass a reference to this class to other classes, I am holding it in a shared_ptr (not sure it actually needs to be held in a shared_ptr, but for fun, it is).
In the class ctor, I use 2 buffers (pointers) and then loop multiple times malloc()'ing, using the buffer and then free()'ing. The dtor should contain failsafe code to free the buffers, in the event of mishap.
The only way the dtor can see the buffers is if I declare them as class variables, however they are only used in the class ctor.
Example:
class Input
{
private:
PSOMETYPE buffer1;
public:
Input();
~Input();
}
Input::Input() : buffer1(NULL)
{
for(blahblah)
{
buffer1 = (PSOMETYPE)malloc(sizeof(SOMETYPE));
// Do work w/buffer1
if(buffer1 != NULL) { free(buffer1); buffer1 = NULL }
}
}
Input::~Input()
{
if(buffer1 != NULL) { free(buffer1); buffer1 = NULL }
}
Considering I only use the buffer in the ctor, does it make sense to declare it as a private class variable? If I declare it in the scope of the ctor, the dtor will have no knowledge as to what it is to free.
I know this is a trivial example, and honestly I could implement this as easily forgetting about using a smart pointer to reference my class and having a blank dtor, just free()'ing as I'm doing inside the loop. I have no mentor or schooling, and I'm uncertain of when the RAII idiom should be followed.
The spirit of RAII would be to use a local object to manage the locally allocated object, rather than artificially tying its lifetime to the object being constructed:
class Input
{
// no pointer at all, if it's only needed in the constructor
public:
Input();
// no explicit destructor, since there's nothing to explicitly destroy
};
Input::Input()
{
for(blahblah)
{
std::unique_ptr<SOMETYPE> buffer1(new SOMETYPE);
// or, unless SOMETYPE is huge, create a local object instead:
SOMETYPE buffer1;
// Do work w/buffer1
} // memory released automatically here
}
You should only ever have to use delete (or free, or whatever) yourself if you're writing a class whose purpose is to manage that resource - and usually there's already a standard class (such as a smart pointer or a container) that does what you want.
When you do need to write your own management class, always remember the Rule of Three: if your destructor deletes something, then the default copying behaviour of the class will almost certainly cause a double delete, so you need to declare a copy constructor and copy-assignment operator to prevent that. For example, with your class I could write the following incorrect code:
{
Input i1; // allocates a buffer, holds a pointer to it
Input i2(i1); // copies the pointer to the same buffer
} // BOOM! destroys both objects, freeing the buffer twice
The simplest way to prevent this is to delete the copy operations, so code like that will fail to compile:
class Input {
Input(Input const&) = delete; // no copy constructor
void operator=(Input) = delete; // no copy assignment
};
Older compilers may not support = delete; in which case you can get almost the same effect by declare them privately without = delete, and not implementing them.