I know there are methods to prevent a class from being created on the heap, by preventing the user from using the new and delete operator. I am trying to do just the opposite. I have a class that I want to prevent the user from creating an instance of it on the stack, and that only instances instigated using the new operator will compile. More specifically, I want the following code to receive an error during compilation:
MyClass c1; //compilation error
MyClass* c1 = new MyClass(); //compiles okay
From searching the web, I found this suggestion on how to do it:
class MyClass {
public:
MyClass();
private:
void destroy() const { delete this; }
...
private:
~MyClass();
};
int main(int argc,char** argv)
{
MyClass myclass; // <--- error, private destructor called here !!!
MyClass* myclass_ptr = new MyClass;
myclass_ptr->destroy();
}
What I don't understand is why this should work. Why would the destructor be called while creating an instance of MyClass?
When myclass reaches the end of its scope (the next }) the compiler calls the destructor to free it from the stack. If the destructor is private, however, then the destructor cannot be accessed, so the class cannot be placed on the stack.
I don't like the look of delete this. In general I think objects should not destroy themselves. Perhaps a better way is to have a private constructor for your class then use a static function to create an instance.
// In class declaration...
static MyClass* Create()
{
return new MyClass(); // can access private constructor
}
// ...
MyClass myclass; // illegal, cannot access private constructor
MyClass* pMyClass = MyClass::Create();
delete pMyClass; // after usage
Why would the destructor be called while creating an instance of MyClass?
It isn't. It must be invoked automatically when the instance goes out of scope, though. If it's private, the compiler must not generate that code, hence the error.
If you think making the destructor private is obscure, another way to restrict a class to dynamic allocation is to make all the constructors private and only have MyClass::create() functions returning dynamically allocated objects:
class MyClass {
public:
static MyClass* create() {return new MyClass();}
static MyClass* create(const Foo& f) {return new MyClass(f);}
private:
MyClass();
MyClass(const Foo&);
};
Note that returning naked pointers to objects that must be deleted is frowned upon. You should return smart pointers instead:
class MyClass {
public:
static std::shared_ptr<MyClass> create() {return new MyClass();}
static std::shared_ptr<MyClass> create(const Foo& f) {return new MyClass(f);}
// ...
};
Because when instance goes out of scope, it has to be destructed using destructor. Pointer to instance does not do this.
Whenever a local variable goes out of scope, it is destroyed.
And on destruction, destructor of object is called. Here, scope is of main function. When program exits, myclass object's destructor will be called
It isn't. The compiler is trying to call the destructor when it goes out of scope, and is indicating to the line of code that produces this effect, which is much more useful than pointing at the end of the function.
Related
I am trying to create and use a std::shared_ptr within a class function whose constructor takes in a std::shared_ptr private data member (of the same class) and another std::shared_ptr created with a raw pointer to the class object (this).
Whenever I call the function that creates the std::shared_ptr (foo), I get a _CrtIsValidHeapPointer(block) assertion. I'm assuming it has something to do with the way in which the shared_ptr is being deleted, but I can't seem to figure it out, and I've searched all over the Internet. Maybe I'm not fully understanding how shared_ptrs work.
Is it not acceptable to create a shared_ptr using the this pointer, or a pre-existing shared_ptr data member?
class Containing_Class;
class Some_Class
{
};
class Set_Value_Command
{
public:
Set_Value_Command(std::shared_ptr<Some_Class> ptr1, std::shared_ptr<Containing_Class> ptr2)
: _ptr1(ptr1), _ptr2(ptr2)
{}
private:
std::shared_ptr<Some_Class> _ptr1;
std::shared_ptr<Containing_Class> _ptr2;
};
class Containing_Class
{
public:
Containing_Class(std::shared_ptr<Some_Class> psc)
: _psc(psc)
{}
void foo()
{
std::shared_ptr<Set_Value_Command> command = std::make_shared<Set_Value_Command>(_psc, std::shared_ptr<Containing_Class>(this));
}
private:
std::shared_ptr<Some_Class> _psc;
};
Here is the main() function. When foo() is called, the assertion happens:
int main()
{
std::shared_ptr<Some_Class> some_class = std::make_shared<Some_Class>();
Containing_Class cc(some_class);
cc.foo();
}
Is it not acceptable to create a shared_ptr using the this pointer
Not by itself, no. And doing so in your example is very bad. Your Containing_Class object is being created in automatic memory of main()'s local stack frame, and thus will be destroyed automatically when it goes out of scope when main() exits. But creating a shared_ptr from this inside of the Containing_Class object will assign ownership of this to the shared_ptr, which will then try to delete this when there are no more shared_ptr references to this. delete'ing an object that was not created with new to begin with is undefined behavior, and is why you are crashing with an error about an invalid heap pointer.
In order to allow shared_ptr to refer to this, Containing_Class would need to derive from std::enable_shared_from_this, and this would have to point at an object that is created dynamically and owned by a shared_ptr. Only then can Containing_Class call its inherited shared_from_this() method to get a shared_ptr to itself.
For example:
class Containing_Class;
class Some_Class
{
};
class Set_Value_Command
{
public:
Set_Value_Command(std::shared_ptr<Some_Class> ptr1, std::shared_ptr<Containing_Class> ptr2)
: _ptr1(ptr1), _ptr2(ptr2)
{}
private:
std::shared_ptr<Some_Class> _ptr1;
std::shared_ptr<Containing_Class> _ptr2;
};
class Containing_Class : public std::enable_shared_from_this<Containing_Class>
{
public:
Containing_Class(std::shared_ptr<Some_Class> psc)
: _psc(psc)
{}
void foo()
{
std::shared_ptr<Set_Value_Command> command = std::make_shared<Set_Value_Command>(_psc, shared_from_this());
}
private:
std::shared_ptr<Some_Class> _psc;
};
int main()
{
auto some_class = std::make_shared<Some_Class>();
auto cc = std::make_shared<Containing_Class>(some_class);
cc->foo();
}
With the code
std::shared_ptr<Containing_Class>(this)
you introduce a second *this owner, i.e. command is the owner of a shared pointer that controls cc life. That is the first issue. Yet another, following issue is that command is pointing to a stack object.
Usually *this is owned by someone and passing ownership to another owner never works.
The current code is impossible to fix due to lack of the code aim.
I'm a beginner to c++ so there are a lot of things quite not clear in my mind.
I have this code I need to write and in a class I make a constructor.
However, I don't need any parameters because I read from a file-stream inside the constructor. So my questions are:
1.Can I make a constructor like this:
class myClass {
private:
string title;
string organizer;
public:
myClass() {
title = stringRead();
organizer = stringRead();
}
}
where stringRead() is a function I have written to read from my file??
2.How do I call it afterwards when I need it? I know that the default constructror is being called like that:
myClass A;
A = myClass();
Is it the same?
3.If I have a pointer, how do I call the constructor again? This doesn't seem like it should be right...
myClass *B;
B = myClass();
Thanks in advance! =D
1) This constructor will work but you should favor using an initialization list (assuming stringRead() isn't a member function of myClass
class myClass {
private:
string title;
string organizer;
public:
myClass()
: title(stringRead()),
organizer(stringRead())
{ }
};
2) myClass A; is what you should be doing. You could alternatively have auto A = myClass(); which, after optimizations, will be the same thing. Without optimizations a temporary will be constructed, and then A will be move constructed from it, so this won't work with unmovable objects (your object is movable)
3) If you want to use a raw pointer then you would use
myClass *ptr = new myClass;
// bunch of code
delete ptr;
However, you'd be better using a smart pointer to control its lifetime. This way you won't need to manually delete
std::unique_ptr<myClass> ptr(new myClass);
or make_unique in c++14
auto ptr = std::make_unique<myClass>();
And of course use a shared_ptr if you have shared ownership
I think it's OK to assign the value returned by a function to a member of a class.
You can initialize it as you suggested (with myClass A;)
When you use pointers, you need myClass *k=new myClass();. You should remember to delete the object you created with delete k;.
Your constructor is fine, so long as the functions used within it are globals or static functions of this or another class.
myClass A; will invoke the constructor you have written.
To use a pointer, you need B = new myClass(). That will also call the same constructor. Don't forget to delete B at some point else you'll leak memory.
Do bear in mind that if an exception is thrown in a constructor then the destructor is not called.
Yes, you can, but it might not be the best approach. Reading from input can fail, failure in a constructor is often a non-recoverable event you'll want to handle. A good approach is reading the values outside the costructor, handling errors and calling the constructor only when you have "everything ready". Like this:
class myClass {
private:
string _title;
string _organizer;
public:
myClass(const string &title, const string &organizer) {
_title = title;
_organizer = organizer;
}
or, by using a more idiomatic C++ initializer list:
class myClass {
private:
string _title;
string _organizer;
public:
myClass(const string &title, const string &organizer):
_title(title), _organizer(organizer) {}
}
and then, somewhere else:
string title = stringRead();
string organizer = stringRead();
myClass A(title, organizer);
No, in this snippet:
myClass A;
A = myClass();
two different things happen: at line 1 the default constructor is called; at line 2, a temporary object is constructed (again, by calling the default constructor) and then assigned to A using the (rval for C++11) copy operator. This expression:
myClass A;
calls the default constructor. If you have parameters:
myClass A(title, organizer);
Nope, this does not even work. A pointer is not an object, you have to allocate the object. At that point, you can get a pointer to it:
myClass A;
myClass *B = &A;
you could also resort to dynamic allocation:
myClass *B = new myClass;
in this case, either remember to call delete B somewhere else or wrap B in a smart pointer:
std::unique_ptr<myClass> B(new myClass());
I need to have a singleton class as I need to initialise some variables only once. I have a problem when I can't to clean up the class as it is crashing. Here is a cut down version of my class:
#include "stdafx.h"
#include <iostream>
class MyClass
{
public:
MyClass();
virtual ~MyClass();
static MyClass& Instance();
void DoSomething();
};
MyClass::MyClass()
{
std::cout<<"MyClass constructor"<<std::endl;
//initialise some stuff here
}
MyClass::~MyClass()
{
std::cout<<"MyClass destructor"<<std::endl;
//clean up some stuff here
}
MyClass& MyClass::Instance()
{
static MyClass _instance;
return _instance;
}
void MyClass::DoSomething()
{
std::cout<<"Do something"<<std::endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
MyClass& myClass = MyClass::Instance();
myClass.DoSomething();
delete &myClass;
return 0;
}
When I call the delete &myClass the destructor gets called and then it blows up like so:
I have investigated and I think that I shouldn't be calling delete on an object that has not been created using new. Is this correct??
Is the answer simply don't use any delete and let the destructor be called automatically when it goes out of scope (When main returns)?
I shouldn't be calling delete on an object that has not been created using new.
Absolutely. It's a static object, which will be destroyed automatically at the end of the program. There's no need (and no way) to destroy it yourself.
(Note that, being static, it's not destroyed when it goes out of scope when Instance() returns. Instead it's destroyed at the end of the program, after returning from main() or calling exit()).
When the static object goes out of scope, they will be deleted automatically, so dont bother calling delete on a static object and you should be fine
Your error is due to the delete (as mentioned by others).
I need to have a singleton class as I need to initialise some variables only once.
No, you really (really, really) don't. Singletons solve the problem of centralizing values/settings, while introducing hidden state, tightening module coupling, hiding module dependencies and rendering code untestable.
Consider using dependency injection instead.
I am trying to understand how to give back memory if one class creates another class.
I have
Clas A;
Then another class that allocate memory for Class A:
class B{
private:
A* data;
public:
// Allocating new memory
B (){
A* data = new A();
//giving memory back
~B(){
delete data; };
};
And when I execute the code in main function it just crashes. What am doing wrong? I am a bit lost here.
Thanks.
Get rid of the redundant A* in the constructor. What this does is create a new, local variable with the same name as your class member. So the real B::data never gets anything assigned to it, and when you try to delete it, things blow up. To add insult to injury, the new A() you assign to the local data will be leaked (well; it would be leaked if the program didn't crash).
class B{
private:
A* data;
public:
// Allocating new memory
B (){
data = new A();
}
//giving memory back
~B(){
delete data;
}
};
That solves the immediate problem, but as juanchopanza noted in the comments, you will still run into problems if you try to copy this object.
Here's the RAII / Rule of Zero route (assuming your compiler supports C++11)
class A {};
class B {
private:
std::unique_ptr<A> data;
public:
B() : data(new A) {
}
};
The RAII handle in this case a unique_ptr will take care of deallocation for you. Implementing it this means the compiler defined copy constructor, copy assignment operator, move constructor, move assignment operator and destructor will all work fine right out the box.
I have code similar to this:
MyClass createInstance()
{
MyClass t;
t.setValue(20);
return t;
}
int main()
{
MyClass primary;
primary.setValue(30);
primary = createInstance();
}
My problem is that createInstance() creates a temporary that is deleted later. In my case, it doesn't use RVO, I have to use The Rule of Three (because my class has a pointer to data members), and I have to do a deep copy of Megabytes of data.
I wonder what's the best way to prevent the creation of a temporary?
Furthermore, I have this MyClass as a member of another class and I would like to prevent the indirection of a pointer and the requirement to manually delete it in the destructor of my parent class.
For example, I could use pointers instead (which would require me to explicitly call the destructor:
MyClass *createInstance()
{
MyClass *t = new MyClass();
t->setValue(20);
return t;
}
int main()
{
MyClass *primary = new MyClass();
primary->setValue(30);
delete primary;
primary = createInstance();
}
Or I could use a member function:
void MyClass::createNewInstance()
{
~MyClass();
init();
setValue(20);
}
int main()
{
MyClass primary;
primary.setValue(30);
primary.createNewInstance();
}
Or I could disallow Assignment/Copying in general:
void MyClass::createInstance()
{
setValue(20);
}
int main()
{
MyClass *primary = new MyClass();
primary->setValue(30);
delete primary;
primary = new MyClass();
primary->createInstance();
}
Am I missing something?
You can't (N)RVO copy into a pre-existing object. The optimization is all about using another freshly created object instead of copying, but in this case the compiler can't guarantee that the assignment object doesn't leave some of the existing state alone (for example).
I would expect that MyClass primary(createInstance()); would enable NRVO for you.
If you really need to assign from a create function your choices are at least two: You can create a temporary and then swap, avoiding the data copy. Alternately with C++11 you could move into the existing object.
Just like what paddy said, how do you know it's not using RVO?
The compiler will do many thing to optimize your code, if it's not in debugging mode.
But, in your creatInstance function, you create a local object, and call a member function on it. The calling of the member function ( t->setValue(20) ) makes it difficult to be optimized, because the compiler will think, the local object is more useful than just an return value. Clearly, we know the local t can be optimized out, but the compiler may not be able to analyze this from its context.
And, by the meaning of "creatInstance", it seems that you just want creat an instance and return it. So, if your constuctor allows to set the value directuly, you can use the RVO:
MyClass creatInstance()
{
return MyClass(20); // if your constuctor makes it possible
}
then, your code will be optimized to this:
// C++ psuedocode
void creatInstance(MyClass* ptr)
{
new (ptr) MyClass(20);
}
int main()
{
MyClass primary;
primary.setValue(30);
// primary = createInstance();
MyClass __temp; // default constructor not called!
creatInstance(&__temp);
primary.operator=(__temp);
// destruct the __temp
}
You may think, it still has to creat temporary object __temp and destroy it , yes, but in your original code, you will creat two temporary object and destroy them, one in your main stack frame, one in your creatInstance function's stack frame.
If you can not sustain the cost of creating temporary object and those stuff, I think you can just change your idea to this:
void modifyInstance(Myclass& objToBeModified)
{
objToBeModified.setValue(20);
// do any change
}
and call it by : modifyInstance ( primary );
by this way, the temporary object creation is definitely prevented!
After all, you just want to change the primary by calling a function, why not writting it directly like above?