How do you delete an instantiated object inside a function then delete when another function is called?
For example:
int function_test(){
object* a = new object();
}
int function_test2(){
delete a;
}
Object a needs to be deleted when function_test2() is called. Function_test() creates and sets the value of object a.
In order to delete something, you need a pointer to something.
When you allocate an object in function function_test and want to delete it in function_test2 you need to take care of a way for function_test2 to get a hold of the pointer to the object you wish to delete.
There are multiple ways of doing that, but the most common one is for function_test to return the pointer to the caller, and then passing that pointer to function_test2:
object* function_test() {
object* a = new object();
...
return a;
}
void function_test2(object* a) {
...
delete a;
}
The caller would need to "transfer" the pointer, like this:
object obj = function_test();
...
function_test2(obj);
Other ways of transferring the pointer are using file-static pointers, using global pointers, and using instance variables when functions function_test and function_test2 are member functions of a class.
You can't transfer local variables between functions. If you like to do something like this, I suggest you return the pointer, so you can pass it to the next function.
object *function_test()
{
auto *o = new object{};
return o;
}
however, this has as disadvantage that you have to capture this variable everywhere where you call it and have to to do memory management. Most likely you just want to use something object oriented, similar to:
class ObjectOwner final
{
public:
int function_test(){
a = new object();
}
int function_test2(){
delete a;
}
private:
object *a{nullptr};
};
which can be used as:
ObjectOwner owner;
owner.function_test();
owner.function_test2();
Even better would be using a std::unique_ptr<object> so that when you forget to call the 2nd function, the memory is freed.
Finally, you can consider using a constructor/destructor.
class ObjectOwner final
{
public:
ObjectOwner()
: a(std::make_unique<object>())
{
}
~ObjectOwner() = default;
void func() { /*Do something with a*/ }
private:
std::unique_ptr<object> a{};
};
Allowing you to write:
ObjectOwner owner{};
owner.func();
Related
I need to use a library which defined a register_cb function taking a void* as it's parameter:
void register_cb(void* data, ...) {
}
Now I wish to pass it some data which I'm not storing on stack, easy way to illustrate is to call this from another function:
void my_processor_fn() {
Foo foo;
register_cb(&foo); //Invalid as foo will go out of scope.
}
So I can use the heap:
void my_processor_fn() {
Foo* foo = new Foo();
register_cb(foo); //Valid but I'll have to call delete to avoid memleak
}
And I can also use smart pointers:
void my_processor_fn() {
std::unique_ptr<Foo> foo(new Foo());
register_cb(&foo); //Invalid, as unique_ptr will go out of scope and will delete foo.
}
How can I leverage smart pointers in these situation when I need to pass void* to a library function, and later the library will call my callback function with the address I have passed into register_cb?
Usually you can extend the lifetime of such objects by putting them in a class. Something like:
class MyProcess {
public:
MyProcess() : data_{std::make_unique<Foo>()} {}
void my_processor_fn() {
register_cb(data_.get());
}
private:
std::unique_ptr<Foo> data_;
};
If you make this object then use it, everything will stay alive for you:
int main() {
MyProcess my_process{};
my_process.my_processor_fn();
// pressumably some spinner that keeps the process alive while callbacks happen.
}
class Example
{
private:
Example* pointer;
Example* pointer2;
public:
Example();
void setPointer2(Example* object);
};
Example::Example()
{
pointer = new Example();
}
void Example::setPointer2(Example* object)
{
this->pointer2 = object;
}
int main()
{
Example object;
object.setPointer2(new Example());
return 0;
}
Delete is not important. I just want to know what is the differences between this two object which is adresses holding by pointer and pointer2. Are they differently allocated? The actual question is, does it matter where to use the "new" operator?
A major problem you have in your code is infinite recursion! The constructor you have defined:
Example::Example()
{
pointer = new Example();
}
creates a new object of its own type. This will call the constructor (again), and that call will call the constructor (again and again...)
But, other than that issue, it doesn't really matter whether you create a new object by directly assigning its address to pointer or if you create the object elsewhere and then assign its address (later) to pointer2. Both will point to an object of the class.
class A
{
int data;
public:
void display()
{
cout<<"Value is "<<data;
}
void set_data(int x)
{
this->data = x;
}
A object = new A();
};
When I run the above code, I get the error stating "new cannot appear in constant expression". Why is it so?
Operator new returns a pointer but A is not a pointer type. You want A*:
A* object = new A();
You also want to move the above statement outside your class body and place it into appropriate function such as main():
int main() {
A* p = new A();
// do work
delete p;
}
That being said you either don't need a pointer at all and you can simply use an object with automatic storage duration:
A object;
Or you want to consider using a smart pointer such as std::unique_ptr:
std::unique_ptr<A> p = std::make_unique<A>();
class A
{
public:
A * object = new A(); // In any case not: "A object = new A();"
};
Or:
class A
{
public:
A object;
};
-
See (let's assume, for a moment, that you don't get the error), in both cases, on the first construction of A object, it creates another A object as a data-member. This A data-member (let's call it object.object ) creates in its turn another A as its data-member (let's call it object.object.object), and so to infinity (or until no more memory). I mean, as a data-member, it can't be either as A* object = new A();, or as A object;
-
I am not sure what was your intention, but if you want to link one A-object to another A-object, the class should be something like that:
class A
{
public:
A * object = nullptr
};
you have to make object of class A into main().
void main(){
A object;
}
First of all, you cannot create an object in the class declaration. Class declaration is like a blue print of the class. It is to say these are the components of my class - variables and member functions. You cannot instantiate anything inside it as no memory is allocated during this stage.
Note that you can instantiate an object inside one of the member function including constructor. These are called during object creation when memory is allocated.
Even if you use this statement inside a constructor you will go into an infinite loop as the constructor calls its constructor and so on until you have memory overflow.
You can declare the object in main like this:
int main() {
A obj = new A();
//other operations
} //Object A is destroyed once you come out of main.
Or dynamically like this
int main() {
A* obj = new A(); //dynamic allocation
//other operations
delete obj; //explicitly destroy
}
Suppose I have:
class A { };
class B : public A { };
A f() {
if (Sunday())
return A;
else
return B;
}
Obviously this doesn't work since A's copy constructor would be called. Is there anyway to return stack allocated object without losing it's type?
I've tried using std::shared_ptr<A> but it got me into another issue since std::shared_ptr<B> isn't std::shared_ptr<A>.
It is not immediately possible to return a stack-allocated (i.e. local) object out of the function that created that object. Local objects are destroyed on function return. You can hide/obfuscate the actual nature of the object's allocation by using various "smart pointers" and similar techniques, but the object itself should be allocated dynamically.
Other that that, as long as the local object lifetime rules are obeyed, polymorphism for local objects works in exactly the same way as it works for any other objects. Just use a pointer or a reference
A a;
B b;
A *p = Sunday() ? &a : &b;
// Here `*p` is a polymorphic object
Pointer p in the above example remains valid as long as the local object lives, which means that you cannot return p from a function.
Also, as you see in the example above, it unconditionally creates both objects in advance, and then chooses one of the two while leaving the second one unused. This is not very elegant. You cannot create different versions of such object in different branches of if statement for the very same reasons for which you cannot return a local object from a function polymorphically: once the local block that created the object is complete, the object is destroyed.
The latter problem can be worked around by using a raw buffer and manual in-place construction
alignas(A) alignas(B) char object_buffer[1024];
// Assume it's big enough for A and B
A *p = Sunday() ? new(buffer) A() : new (buffer) B();
// Here `*p` is a polymorphic object
p->~A(); // Virtual destructor is required here
but it does not look pretty. A similar technique (involving copying of the buffer) can probably be used to make local polymorphic objects survive block boundaries (see #Dietmar Kühl's answer).
So, again, if you want to create only one object of the two and have your object to survive block boundaries, then immediate solutions put local objects are out of the question. You will have to use dynamically allocated objects.
It's not possible because of slicing. Use std::unique_ptr instead. You won't lose the dynamic type, but it will be accessible only through the interface of A.
The easiest approach is certainly to use a suitable smart pointer, e.g., std::unique_ptr<A>, as the return type and to allocate the object on the heap:
std::unique_ptr<A> f() {
return std::unique_ptr<A>(Sunday()? new B: new A);
}
For the approach returning a std::unique_ptr<A> which may point to a B, it is necessary that A has a virtual destructor as otherwise the code may result in undefined behavior when the std::unique_ptr<A> actually points to a B object. If A doesn't have a virtual destructor and can't be changed, the problem can be avoided by using a suitable std::shared_ptr<...> or by using a suitable deleter with the std::unique_ptr<...>:
std::unique_ptr<A, void(*)(A*)> f() {
if (Sunday()) {
return std::unique_ptr<A, void(*)(A*)>(new B, [](A* ptr){ delete static_cast<B*>(ptr); });
}
else {
return std::unique_ptr<A, void(*)(A*)>(new A, [](A* ptr){ delete ptr; });
}
}
If you don't want to allocate the objects on the heap, you can use a holder type which stores a union with A and B which is then appropriately constructed and destructed (the code below assumes that the copy of A or B won't throw an exception; if necessary, suitable move construction and move assignment can be added):
class holder {
bool is_b;
union {
A a;
B b;
} element;
public:
holder(): is_b(Sunday()) {
if (this->is_b) {
new(&this->element.b) B();
}
else {
new(&this->element.a) A();
}
}
holder(holder const& other) { this->copy(other); }
void copy(holder const& other) {
this->is_b = other.is_b;
if (this->is_b) {
new(&this->element.b) B(other.element.b);
}
else {
new(&this->element.a) A(other.element.a);
}
}
~holder() { this->destroy(); }
void destroy() {
if (this->is_b) {
this->element.b.~B();
}
else {
this->element.a.~A();
}
}
holder& operator= (holder const& other) {
this->destroy();
this->copy(other);
return *this;
}
operator A const&() const { return this->is_b? this->element.b: this->element.a; }
operator A&() { return this->is_b? this->element.b: this->element.a; }
};
I've a situation like this:
class MyClass
{
private:
std::auto_ptr<MyOtherClass> obj;
public:
MyClass()
{
obj = auto_ptr<MyOtherClass>(new MyOtherClass());
}
void reassignMyOtherClass()
{
// ... do funny stuff
MyOtherClass new_other_class = new MyOtherClass();
// Here, I want to:
// 1) Delete the pointer object inside 'obj'
// 2) Re-assign the pointer object of 'obj' to 'new_other_class'
// so that 'obj' now manages 'new_other_class' instead of the
// object that just got deleted manually
}
};
Is there a way to achieve this? Will the following code do what I want?
void MyClass::reassignMyOtherClass()
{
// ... still, do more funny stuff (flashback humor :-)
MyOtherClass new_other_class = new MyOtherClass();
obj.reset(new_other_class);
}
Will the memory of new_other_class be de-allocated in the default destructor of MyClass?
Yes it will.
You can use
obj.reset( new MyOtherClass() );
And I'd better use such constructor
MyClass():
obj( new MyOtherClass() )
{
}
From MSDN where describing reset
The member function evaluates the expression delete myptr, but only if the stored pointer value myptr changes as a result of function call. It then replaces the stored pointer with ptr.
It will do what you want.