My question is this: after deleting a constructor is there any way to initialize a class? For example
class A{
public:
A() = delete;
int a = 42;
int fun(){
a += 1;
return a;
}
};
Now it should not be possible to use this class. For example you cannot:
A* instance = (A*)malloc(sizeof(A));
instance->fun(); //segfault
and
A instance; //compile error undefined function
Assuming for some strange reason you actually wanted to use the class with the constructor deleted is there a way that you could do it? That is without doing something like overriding the constructor.
I know this is a strange question, but I am interested in knowing if someone has a (perhaps obscure) way of doing this. Thanks!
If the class is an aggregate you can create one using aggregate initialization, which does not call a constructor of A. For example:
A a = { 1 };
In C++11 your class was not an aggregate because of the presence of the = 42. So in C++11 your class is unusable.
But in C++14 this was changed, and = 42 does not prevent the class being an aggregate, so it is usable again.
The reason this is allowed is that calling malloc is not equivalent to calling new. malloc merely allocates memory and returns where it begins; new allocates and constructs an object. Just directly creating an A, as in A instance;, runs the constructor as well - so it expects it to be there.
As such, it is not an error as you never actually construct any A object. You allocate uninitialized memory, cast the pointer to A*, and then call it. This is valid because the language and the compiler don't care (or likely know) where you got that memory. All it knows is that at runtime, instance contains valid allocated memory; if that were not the case, it might segfault (it also might not, but would still probably be bad).
What happens when you actually run this is that fun() will access uninitialized memory as if it were an A; as such, int a will be something, but probably not 42.
It's not required that a pointer be to a constructable class. For example, you can cast an actual class pointer to one of its non-constructable interface classes and still access it. Effectively, the same methodology that allows that allows this.
Related
Is it possible to call the destructor of an object without knowing the class type without using delete? I am asking because I am working on an allocator (for fun/ practice) and I am using malloc/ placement new to constructor the object but then when I go to destruct the object, I was curious if there was a way to do so without knowing the type. If it is not possible, why not? Is it the only way to do is the way I show in my sample code (that is commented out)?
#include <stdio.h>
#include <new>
void* SomeAllocationFunction(size_t size) {
return malloc(size);
}
class SomeClass{
public:
SomeClass() {
printf("Constructed\n");
}
~SomeClass() {
printf("Destructed\n");
}
};
int main(void){
void* mem = SomeAllocationFunction(sizeof(SomeClass));
SomeClass* t = new(mem)SomeClass;
free(t);
//t->~SomeClass(); // This will call the destructor, is it possible to do this without knowing the class?
return 0;
}
(I know I can just call delete, but please ignore that for the moment.)
No, it's not possible without knowing the type (or knowing one of the object's base types that has a virtual destructor).
Typically speaking, custom allocators neither construct nor destruct the object, though some make a templated wrapper around the allocator that performs a placement new or a direct destructor call.
(Technically, you could associate with every allocation a function pointer that ends up calling the type's destructor. But that's fairly sketchy, and I wouldn't recommend it.)
No, you can't call the destructor without knowing the class, because the compiler doesn't know which destructor to call. You could either:
Make all objects inherit from some base object that has a virtual destructor, and use that base object pointer instead of a void pointer
Make use of templates
Have the allocator itself not manage the calling of constructors/destructors
It is no more possible to call the destructor on an untyped piece of memory than it is to call a constructor (ie: placement new) without a type. Both the constructor and the destructor are part of the object, and the compiler needs a type to know what to call.
As of C++17 this has become possible with std::destroy_at. See CPP Reference.
Take a small example where, I am trying to find out if a variable is allocated on heap or not:
struct A
{
bool isOnHeap;
A () {} // not touching isOnHeap
~A () {}
void* operator new (size_t size)
{
A* p = (A*) malloc(size);
p->isOnHeap = true; // setting it to true
return p;
}
void operator delete (void *p) { free(p); }
};
It gives expected result in g++-4.5 (with warning for stack object). Is it ill defined
to do such operations ?
You can't initialize class members in an overloaded operator new because the object's lifetime hasn't started. You can only initialize members during the construction of the object.
You have no guarantee that the implementation won't wipe the memory between the time operator new returns and the time the object's construction starts or that during object construction members that are specified to have an indeterminate value by the standard (e.g. because they are POD and not explicitly initialized in the constructor like isOnHeap) aren't deliberately set to something by the implementation.
Note that A has a non-trivial constructor (it is user-declared), so its lifetime doesn't start when the storage for the object is allocated (ISO/IEC 14882:2003, 3.8 [basic.life] / 1) and the program has undefined behavior if it uses a pointer to the storage for the object to access a non-static data member (3.8 / 5). Even if A was a POD type, it's value after the completion of the new-expression would still be indeterminate rather than necessarily being related to the values in the bytes in the storage for the object before the new-expression was evaluated.
As Charles said, the object only comes to lifetime after it has been newed, so setting data within your implementation of new is rather dangerous.
Also, when your developers use tools like Lint, there's a big chance that it complains that the member isOnHeap is not initialized in the constructor. If then someone thinks "hey, Lint is right, let's initialize isOnHeap in the constructor of A", this will undermine the mechanism that you try to achieve.
There is a second case of which you probably didn't think. Suppose that someone writes this:
class MyClass
{
public:
...
private:
struct A m_a;
};
int main()
{
MyClass *myVariable = new MyClass();
}
Then your implementation of new will not be called. Nevertheless the instance of A is allocated on the heap (as part of the MyClass instance).
Can you explain why you want to know whether something has been allocated on the heap or not? Maybe there's another, more elegant solution to your problem.
Even when not considering the operator new itself (which is nonstandard and I would even say ugly, but knowing the exact details of some particular compiler it might be workable), there is another problem with this, which renders it useless anyway: You have no guarantee the value od isOnHeap will not be true when allocated on the stack. The stack is not initialized and any garbage from function invocations done before can be found there.
struct A
{
A(int a);
};
struct B
{
B();
void b(std::shared_ptr<A> a);
};
int main()
{
A a(1);
B b;
b.b(&a);
}
So I got this error, sorry guys it's my frist time with the smart pointers!!
Error:
no suitable constructor exists to convert from "A *" to "std::tr1::shared_ptr<A>"
How do I fix this problem!?
The entire point of a smart pointer is to have ownership. That is, it's responsible for the deallocation of whatever it's pointing it. It simply doesn't make sense to try to tell it to manage something that's already being managed by a completely different system.
In your case, a is already being automatically managed, why would you want to also be managed by a smart pointer? Even if that worked, you'd just be setting yourself for deleting it twice, which is UB.
Either give it something to own, like new A(1), or change b to operate on something it doesn't own.
Others already ranted on the design error of your code, but not the real problem why the code doesn't even compile. shared_ptr has a constructor that accepts a raw pointer, but it is marked as explicit, which means you have to explicitly write out that you want to construct a shared_ptr instance. What your function call tries, is to do that construction implicitly, which isn't allowed because of the explicit keyword.
The following will compile but give undefined behaviour because the shared_ptr will (try to) delete an object which resides on the stack and is as such not deleteable:
b.b(shared_ptr<A>(&a)); // explicit construction
A special trait of shared_ptr is that you can pass the constructor a deleter, which will be called when the owned pointer should be deleted. You can just write and use a "noop" deleter, which does just nothing; the following will not invoke undefined behaviour and will not try to delete the stack variable:
// outside of main
void noop_deleter(A*){/*do nothing*/}
// call...
b.b(shared_ptr<A>(&a, noop_deleter));
And there actually is a use for this, if you have a library API that absolutely wants a shared_ptr but you want to call it with a stack variable. The design of that API is another thing though...
std::tr1::shared_ptr has one constructor that allows to pass down a given raw pointer. So if you had a pointer to A, you would do something like:
std::shared_ptr (pMyA)
but in your case, your pointer to A points to an automatic variable NOT to a dynamically allocated memory resource that can be deleted after usage.
Something like this would be a better use case:
class B
{
void b (shared_ptr <A> pA) {}
}
int main ()
{
shared_ptr<A> pA (new A);
B b;
b.b (pA);
...
}
If I create a class MyClass and it has some private member say MyOtherClass, is it better to make MyOtherClass a pointer or not? What does it mean also to have it as not a pointer in terms of where it is stored in memory? Will the object be created when the class is created?
I noticed that the examples in QT usually declare class members as pointers when they are classes.
If I create a class MyClass and it has some private member say MyOtherClass, is it better to make MyOtherClass a pointer or not?
you should generally declare it as a value in your class. it will be local, there will be less chance for errors, fewer allocations -- ultimately fewer things that could go wrong, and the compiler can always know it is there at a specified offset so... it helps optimization and binary reduction at a few levels. there will be a few cases where you know you'll have to deal with pointer (i.e. polymorphic, shared, requires reallocation), it is typically best to use a pointer only when necessary - especially when it is private/encapsulated.
What does it mean also to have it as not a pointer in terms of where it is stored in memory?
its address will be close to (or equal to) this -- gcc (for example) has some advanced options to dump class data (sizes, vtables, offsets)
Will the object be created when the class is created?
yes - the size of MyClass will grow by sizeof(MyOtherClass), or more if the compiler realigns it (e.g. to its natural alignment)
Where is your member stored in memory?
Take a look at this example:
struct Foo { int m; };
struct A {
Foo foo;
};
struct B {
Foo *foo;
B() : foo(new Foo()) { } // ctor: allocate Foo on heap
~B() { delete foo; } // dtor: Don't forget this!
};
void bar() {
A a_stack; // a_stack is on stack
// a_stack.foo is on stack too
A* a_heap = new A(); // a_heap is on stack (it's a pointer)
// *a_heap (the pointee) is on heap
// a_heap->foo is on heap
B b_stack; // b_stack is on stack
// b_stack.foo is on stack
// *b_stack.foo is on heap
B* b_heap = new B(); // b_heap is on stack
// *b_heap is on heap
// b_heap->foo is on heap
// *(b_heap->foo is on heap
delete a_heap;
delete b_heap;
// B::~B() will delete b_heap->foo!
}
We define two classes A and B. A stores a public member foo of type Foo. B has a member foo of type pointer to Foo.
What's the situation for A:
If you create a variable a_stack of type A on the stack, then the object (obviously) and its members are on the stack too.
If you create a pointer to A like a_heap in the above example, just the pointer variable is on the stack; everything else (the object and it's members) are on the heap.
What does the situation look like in case of B:
you create B on the stack: then both the object and its member foo are on the stack, but the object that foo points to (the pointee) is on the heap. In short: b_stack.foo (the pointer) is on the stack, but *b_stack.foo the (pointee) is on the heap.
you create a pointer to B named b_heap: b_heap (the pointer) is on the stack, *b_heap (the pointee) is on the heap, as well as the member b_heap->foo and *b_heap->foo.
Will the object be automagically created?
In case of A: Yes, foo will automatically be created by calling the implicit default constructor of Foo. This will create an integer but will not intitialize it (it will have a random number)!
In case of B: If you omit our ctor and dtor then foo (the pointer) will also be created and initialized with a random number which means that it will point to a random location on the heap. But note, that the pointer exists! Note also, that the implicit default constructor won't allocate something for foo for you, you have to do this explicitly. That's why you usually need an explicit constructor and a accompanying destructor to allocate and delete the pointee of your member pointer. Don't forget about copy semantics: what happens to the pointee if your copy the object (via copy construction or assignment)?
What's the point of all of this?
There are several use cases of using a pointer to a member:
To point to an object you don't own. Let's say your class needs access to a huge data structure that is very costly to copy. Then you could just save a pointer to this data structure. Be aware that in this case creation and deletion of the data structure is out of the scope of your class. Someone other has to take care.
Increasing compilation time, since in your header file the pointee does not have to be defined.
A bit more advanced; When your class has a pointer to another class that stores all private members, the "Pimpl idiom": http://c2.com/cgi/wiki?PimplIdiom, take also a look at Sutter, H. (2000): Exceptional C++, p. 99--119
And some others, look at the other answers
Advice
Take extra care if your members are pointers and you own them. You have to write proper constructors, destructors and think about copy constructors and assignment operators. What happens to the pointee if you copy the object? Usually you will have to copy construct the pointee as well!
In C++, pointers are objects in their own right. They're not really tied to whatever they point to, and there's no special interaction between a pointer and its pointee (is that a word?)
If you create a pointer, you create a pointer and nothing else. You don't create the object that it might or might not point to. And when a pointer goes out of scope, the pointed-to object is unaffected. A pointer doesn't in any way affect the lifetime of whatever it points to.
So in general, you should not use pointers by default. If your class contains another object, that other object shouldn't be a pointer.
However, if your class knows about another object, then a pointer might be a good way to represent it (since multiple instances of your class can then point to the same instance, without taking ownership of it, and without controlling its lifetime)
The common wisdom in C++ is to avoid the use of (bare) pointers as much as possible. Especially bare pointers that point to dynamically allocated memory.
The reason is because pointers make it more difficult to write robust classes, especially when you also have to consider the possibility of exceptions being thrown.
I follow the following rule: if the member object lives and dies with the encapsulating object, do not use pointers. You will need a pointer if the member object has to outlive the encapsulating object for some reason. Depends on the task at hand.
Usually you use a pointer if the member object is given to you and not created by you. Then you usually don't have to destroy it either.
This question could be deliberated endlessly, but the basics are:
If MyOtherClass is not a pointer:
The creation and destruction of MyOtherClass is automatic, which can reduce bugs.
The memory used by MyOtherClass is local to the MyClassInstance, which could improve performance.
If MyOtherClass is a pointer:
The creation and destruction of MyOtherClass is your responsibility
MyOtherClass may be NULL, which could have meaning in your context and could save memory
Two instances of MyClass could share the same MyOtherClass
Some advantages of pointer member:
The child (MyOtherClass) object can have different lifetime than its parent (MyClass).
The object can possibly be shared between several MyClass (or other) objects.
When compiling the header file for MyClass, the compiler doesn't necessarily have to know the definition of MyOtherClass. You don't have to include its header, thus decreasing compile times.
Makes MyClass size smaller. This can be important for performance if your code does a lot of copying of MyClass objects. You can just copy the MyOtherClass pointer and implement some kind of reference counting system.
Advantages of having the member as an object:
You don't have to explicitely write code to create and destroy the object. It's easier and and less error-prone.
Makes memory management more efficient because only one block of memory needs to be allocated instead of two.
Implementing assignment operators, copy/move constructors etc is much simpler.
More intuitive
If you make the MyOtherClass object as member of your MyClass:
size of MyClass = size of MyClass + size of MyOtherClass
If you make the MyOtherClass object as pointer member of your MyClass:
size of MyClass = size of MyClass + size of any pointer on your system
You might want to keep MyOtherClass as a pointer member because it gives you the flexibility to point it to any other class that is derived from it. Basically helps you implement dynamice polymorphism.
It depends... :-)
If you use pointers to say a class A, you have to create the object of type A e.g. in the constructor of your class
m_pA = new A();
Moreover, don't forget to destroy the object in the destructor or you have a memory leak:
delete m_pA;
m_pA = NULL;
Instead, having an object of type A aggregated in your class is easier, you can't forget to destroy it, because this is done automatically at the end of lifetime of your object.
On the other hand, having a pointer has the following advantages:
If your object is allocated on the
stack and type A uses a lot of memory
this won't be allocated from the
stack but from the heap.
You can construct your A object later (e.g. in a method Create) or destroy it earlier (in method Close)
An advantage of the parent class maintaining the relation to a member object as a (std::auto_ptr) pointer to the member object is that you can forward declare the object rather than having to include the object's header file.
This decouples the classes at build time allowing to modify the member object's header class without causing all the clients of your parent class to be recompiled as well even though they probably do not access the member object's functions.
When you use an auto_ptr, you only need to take care of construction, which you could typically do in the initializer list. Destruction along with the parent object is guaranteed by the auto_ptr.
The simple thing to do is to declare your members as objects. This way, you do not have to care about copy construction, destruction and assignment. This is all taken care of automatically.
However, there are still some cases when you want pointers. After all, managed languages (like C# or Java) actually hold member objects by pointers.
The most obvious case is when the object to be kept is polymorphic. In Qt, as you pointed out, most objects belong to a huge hierarchy of polymorphic classes, and holding them by pointers is mandatory since you don't know at advance what size will the member object have.
Please beware of some common pitfalls in this case, especially when you deal with generic classes. Exception safety is a big concern:
struct Foo
{
Foo()
{
bar_ = new Bar();
baz_ = new Baz(); // If this line throw, bar_ is never reclaimed
// See copy constructor for a workaround
}
Foo(Foo const& x)
{
bar_ = x.bar_.clone();
try { baz_ = x.baz_.clone(); }
catch (...) { delete bar_; throw; }
}
// Copy and swap idiom is perfect for this.
// It yields exception safe operator= if the copy constructor
// is exception safe.
void swap(Foo& x) throw()
{ std::swap(bar_, x.bar_); std::swap(baz_, x.baz_); }
Foo& operator=(Foo x) { x.swap(*this); return *this; }
private:
Bar* bar_;
Baz* baz_;
};
As you see, it is quite cumbersome to have exception safe constructors in the presence of pointers. You should look at RAII and smart pointers (there are plenty of resources here and somewhere else on the web).
When can an object of a class call the destructor of that class, as if it's a regular function? Why can't it call the constructor of the same class, as one of its regular functions? Why does the compiler stops us from doing this?
For example:
class c
{
public:
void add() ;
c();
~c() ;
};
void main()
{
c objC ;
objC.add() ;
objC.~c() ; // this line compiles
objC.c() ; // compilation error
}
By definition, a constructor is only called once, when the object is created. If you have access to an object, then it must have been created, so you're not allowed to call the constructor again - this is the reason why explicit constructor calls are not allowed. Similarly, destructors must only be called once, when the object is destroyed. If this could always done automatically, then the language would also forbid explicit destructor calls.
However, in some circumstances, you might want precise control over memory management, and the ability to explicitly create and destroy objects within memory that you are managing. For this purpose, the language provides "placement new" to create an object at an arbitrary location, and explicit destructor calls to destroy objects created this way. An explicit constructor call wouldn't be useful, since you need to be able to specify the location of the new object - so you get "placement new" instead. An explicit destructor call is sufficient, so there's no need to invent some sort of matching "placement delete".
So: there is no valid use for explicit constructor calls, so they are not allowed. There is a valid use for explicit destructor calls, so they are (syntactically) allowed, with the rule that you must only ever use them on objects that won't otherwise be destroyed, i.e. objects created using "placement new", and in that case call them exactly once. Using them in any other way, like so many C++ errors, will compile but give undefined behaviour.
I think you can explicitly call the destructor if you make sure that the instance is replaced/recreated with a call to placement new:
class c
{
public:
void add() ;
c();
~c() ;
};
int main()
{
c objC ;
objC.add() ;
objC.~c() ; // this line compiles
new (&objC) c; // placement new invokes constructor for the given memory region
}
I've never seen this in practice, but logically it should work (unless c's constructor can throw, in which case, I imagine, hell could break loose during stack unwinding).
However, what you probably want is just assignment:
objC = c();
If the destructor has side-effects that you are interested in, implement assignment using the copy-and-swap idiom which gets the destructor invoked for the "left-hand" value.
A destructor must be called on an existing instance of a class - destructing the instance is what it does. A constructor creates a brand new instance of a class, so calling on an existing instance makes no sense.
This is similar to the way new and delete work:
int * p = new int; // call to new needs no existing instance
delete p; // call to delete requires existing instance
And note in your code, the object would be destroyed twice, once explicitly, and once implicitly at the end of its enclosing scope. You typically only explicitly call a destructor if you are doing something unusual, probably involving the use of placement new.
If you really need to do something like this, just create an additional function and call it from outside AND from the constructor itself, but let's see what happens when you do need such a call:
#include<new>
class A
{
//members
};
int main()
{
//allocate buffer
char* buffer = new char[sizeof(A)];
//construct A on that memory space
A * ptrToA = ::new (buffer) A();
//destroy the object
ptrToA->~A();
//deallocate the buffer
delete[] buffer;
}
One instance where you can find placement new usage is the standard
containers. The allocator takes in the responsibility to allocate the
buffer (allocate member) and the objects are constructed over that
buffer as they are added into the container. For example, when you do
reserve on vector object, it reserves the space for N objects meaning
allocates space for N objects but does not construct them. Then when
you do push_back etc, to add elements, they are created over that
buffer. Basically, it is a technique to reduce the overhead of
repeated calls to memory allocation function. And then when done, the
vector destructor would destroy the objects calling the destructor
explicitly for all objects in it and then call the deallocate()
function of the allocator to release the memory. Hope this helps.
Try this out :
obj.ClassName::ClassName() ; // it works in VC 6.0 compiler
Another way to think about the restriction is that a constructor is not just another function. Consider its definition: unlike other functions, it has no return value, and it may have an initializer list. That it just happens to have most of the syntax of a function is kind of a coincidence; it really exists only for the purpose of initializing a new instance of an object.
The constructor is there "c()" used with new, i.e.
c objC = new c();
If you want to call your constructor outside of the actual construction of the class instance then you either haven't understood the purpose of the constructor or are trying to put functionality in there that shouldn't be there.
You are asking about a particular style of syntax more than a language limitation. C++ allows you to call an object's constructor or destructor.
c objC;
objC.~c(); // force objC's destructor to run
new(&objC); // force objC's constructor to run
Why did the language designers not use this syntax instead?
c objC;
delete(&objC) c; // force objC's destructor to run
new(&objC) c; // force objC's constructor to run
Or why not:
c objC
objC.~c(); // force objC's destructor to run
objC.c(); // force objC's constructor to run
My opinion as to why they chose the syntax they did:
The first alternative is more flexible than the second. I can call the constructor / destructor on any address not just an instance. That flexibility is needed for allocation, but not for destruction. Also the first option's delete seems to be very dangerous once virtual destructors get in to the mess.
you can invoke the constructor of an instance's class using typeof:
class c
{
public:
void add() ;
c();
~c() ;
};
void main()
{
c objC ;
objC.add() ;
objC.~c() ; // this line compiles (but is a bad idea)
typeof objC otherObjC; // so does this.
}
This does not affect the value of the instance objC, but creates a new instance otherObjC using objC's class constructor.
Note: this may do something you don't expect if the static type is a baseclass of the dynamic type of the instance you have.
Who says you can't? You just have to know how.
void Foo::Bar() {
*this = Foo(); // Reset *this
}