Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed yesterday.
Improve this question
I'm having difficulties understanding the following code:
class Base{
Base(){/* do stuff */};
};
class Deriv: public Base{
Deriv(){/* do stuff */};
};
// I have a problem understanding the purpose of the next line
Base &foo = *(new Deriv());
First, you need to be familiar with Polymorphism, references, dereferencing and temporary object behavior.
Every object of some Class can be represented as (can be treated as) an object of a Class that is higher in the hierarchy.
The most popular examples of this are animals. Many sources describe this topic with it.
class Animal {};
class Dog : public Animal {};
int main() {
// All dogs are animals: OK
Animal* a = new Dog();
// Not every animal is a dog: Error
Dog* d = new Animal()
}
Imagine you are creating a game, where your player has a pet.
class WongPlayer {
Dog* pet;
}
If you put it this way, you will be able to have only Dog as pet.
class CorrectPlayer {
Animal* pet;
}
In this case, you can have as pet any class that inherits from Animal.
This was just one simple example of the usage of Polymorphism.
References.
The best way of explaining what references are is to treat them as aliases.
Creating a reference is completely identical of creating an alias.
And all the restrictions are also well understood by this way.
Example:
int a = 5;
int& b = a; // b is alias of a
b = 3; // a = 3
Dereferencing.
new returns a pointer, so to work with the object it points to, you have to first dereference it.
Example:
int* val = new int(1);
val = 5; // Error can't assign int to pointer
*val = 5; OK
delete val;
Temporary objects, they are created and deleted immediately.
Example:
class A {
public:
A() { std::cout << "Created" << std::endl;}
~A() { std::cout << "Destroyed" << std::endl;}
}
int main {
A();
std::cout << "Should it be printed before destruction? No!" << std::endl;
return 0;
}
In your case, you do the following:
Allocate an object in heap and return its pointer.
new Deriv()
Dereference that pointer
*(new Deriv())
Create a reference and bind it with newly created object.
And here we start to have some problems. It is not a temporary object! Your object in heap never gets destroyed.
It is a clear memory leak
I don't know why are you creating a reference.
The best way is to create a pointer.
Base* ptr = new Deriv();
And then
delete ptr;
And that's it.
But yes, you can also delete it like this
Base& ref = *(new Deriv());
delete &ref;
Related
This question already has answers here:
Why doesn't polymorphism work without pointers/references?
(6 answers)
Closed 2 years ago.
Given the following code:
class Base {
public:
virtual void Test() {
cout << "Not Overridden" << endl;
}
};
class Derived : public Base {
public:
void Test() override {
cout << "Overridden" << endl;
}
};
int main() {
Base o = Derived();
o.Test();
return 0;
}
Someone like me who is from a Java background, expects the compiler to output Overridden but surprisingly the output is exactly the otherwise.
If this is a normal behavior, then what's the point of inheritance in C++ at all?
What is that I am missing?
Yes, it's normal behavior, polymorphism only works with pointers and references.
With raw pointer:
int main() {
Base* o = new Derived();
o->Test();
delete o; //when done with using it delete it from memory
//...
}
An alternative to this memory management would be to use smart pointers.
With smart pointer:
int main() {
unique_ptr<Base> o(new Derived); // automatic memory management
o->Test();
//...
}
With reference:
int main() {
Derived d;
Base& o = d;
o.Test();
//...
}
This is something you need to be careful with, when the block where Derived object was declared goes out of scope, the reference will be rendered useless, for example, if you return it from a function.
Output:
Overridden
Some threads on the site explain why this is so, like this one.
The way you have it leads to object slicing.
You'll also want to add a virtual destructor to your base class.
Base o = Derived();
o above is an object – a Base object – not a Derived one. The o object is created from a Derived object by means of object slicing, but o is still a Base object. There is no dynamic dispatch here, so o.Test() results in Base::Test() being called.
Instead, if you declare o as a Base pointer that refers to the Derived object you create:
Base* o = new Derived();
o->Test();
In this case, o is a pointer to an object – as opposed to an object – and dynamic dispatch takes effect: Even though o is a pointer to a Base object, it is bound to a Derived object, so o->Test() results in Derived::Test() being called this time due to dynamic dispatch.
Analogously if o is a reference to Base instead of a pointer.
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
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Quick question,
I'm new to C++ and I'm having difficulty understanding the destructors.
I'll explain; lets say we have the following;
int _a;
a::a(int x) {
_a = x
}
then we have
a* a1 = new a(8);
I understand that a1's data is created on the heap, and a1 is a pointer, where I'm failing is with the destructor;
a::~a() {
// confusion here
}
Since _a is not a pointer since it was created implicitly on the heap thanks to new (correct) we cannot delete it so what do we do?
Does
delete a1;
call the destructor for a int automatically?
call the destructor for a int automatically?
That would be true if the object were a class type. For non-class types, there is no destrutor, not even implicitly defined ones. Hence, the question of calling the destructor does not arise.
Had your code been something like:
struct Foo
{
Foo() {}
~Foo() {}
};
struct a
{
Foo f
};
a* aptr = new a;
delete aptr;
The destructor, Foo::~Foo(), will be called for f.
I understand what you're driving at and the answer is no, C++ destructors do not automatically destroy the data that your class contains. Unfortunately your example is too contrived to highlight the problem well. int is a primitive type so its destruction is primitive (someone might want to comment on what actually happens in ints destructor). Take the following example:
class A
{
public:
int x;
~A()
{
std::out << "in A destructor" << std::endl;
}
};
class B
{
public:
A* x;
B()
{
x = new A();
}
~B()
{
std::out << "in B destructor" << std::endl;
// does not automatically delete x
}
};
auto x = new B();
delete x;
In this example, constructing an instance of B will also construct an instance of A because you explicitly new it up in the constructor of B. However, unless you explicitly delete x in your destructor for B it will not automatically be deleted.
A slight variation of me previous example would be if B::x were of type A and not A*, in which case the answer is yes, the destructor for A would be called.
I hope this helps!
The destructor is just a function that is called automatically when the instance comes out of scope. It's a convenient way to release dynamically allocated memory.
You don't have to worry about releasing variables that were allocated on the stack (anything that is declared and not new-ed).
For example:
int localStackVar = 5; //no need to deallocate explicitly
int* localPointer = &localStackVar // no need to deallocate explicitly
int* heapValue = new int(); //Allocates to the heap so you need to call delete explicitly
The first two from the example above are on the stack, the first one is an int and the second is an int pointer, which is just a way to say it's a variable that holds the memory address of another variable.
Both of those will be deallocated automatically, since you did not call new on them.
The third line allocates an int on the heap. You have to call delete on it when you don't need it anymore.
If those 3 variables were a part of a class, your constructor and destructors would look like this:
MyClass::MyClass()
{
heapValue = new int();
}
MyClass::~MyClass() //destructor
{
delete heapValue;
}
void someFun()
{
MyClass instance; //constructor is called here
//do stuff
return; //destructor is called here
}
So while MyClass instance is a local stack variable when declared in someFun
since the constructor is called automatically, heapVal is made to point to a memory location that is on the heap which needs to be released explicitly.
If your destructor did not call delete on it, the memory would "leak" it will not be released until your program terminates.
Been running into a snag while working in C++. I've tried several answers on SO, as well as other places (like: returning an abstract class from a function, and How do I make an abstract class properly return a concrete instance of another abstract class?), but I've still been having trouble-- these don't seem to completely fit...
I have an abstract class, a derived class:
class AbstractClass {
virtual std::string virtMethod() = 0;
}
class Derived : public AbstractClass {
std::string virtMethod();
}
Also, I a separate class which I'm trying to get a return type of the abstract class (of course, returning an instance of the derived class).
I've tried using pointer and reference:
AbstractClass* methodFromOtherClass() {
if (somethingIsTrue) {
Derived d = Derived();
return &d;
}
SomeOtherDerived s = SomeOtherDerived();
return &s;
}
Which, in Xcode, gives me the warning:
Address of stack memory associated with local variable 'd' returned
I tried creating a static Derived object and was unable to then destroy it in the method which calls my "methodFromOtherClass()."
I've also tried my hand at smart pointers (though someone may point out my obvious misuse of them):
std::unique_ptr<AbstractClass> methodFromOtherClass() {
if (somethingIsTrue) {
Derived d = Derived();
return std::unique_ptr<AstractClass>(&d);
}
SomeOtherDerived s = SomeOtherDerived();
return std::unique_ptr<AstractClass>(&s);
}
The above, perhaps unsurprisingly, gives me a segfault.
I'm used to being able to do this easily in Java... Any help would be appreciated. C++ isn't a very strong language for me at the moment, so it could be something very basic which I'm overlooking.
In both tries, you have made the same mistake: Returning a pointer to a local variable. Do not ever do that! What you need is to create a new instance of your class in heap memory instead.
Without std::unique_ptr:
AbstractClass* methodFromOtherClass() {
if (somethingIsTrue) {
Derived* d = new Derived();
return d;
}
SomeOtherDerived* s = new SomeOtherDerived();
return s;
}
AbstractClass *c = obj->methodFromOtherClass();
...
delete c;
Or with std::unique_ptr:
std::unique_ptr<AbstractClass> methodFromOtherClass() {
if (somethingIsTrue) {
Derived d = new Derived();
return std::unique_ptr<AbstractClass>(d);
}
SomeOtherDerived* s = new SomeOtherDerived();
return std::unique_ptr<AbstractClass>(s);
/*
Or better, with std::make_unique():
if (somethingIsTrue) {
return std::make_unique<Derived>();
}
return std::make_unique<SomeOtherDerived>();
*/
}
std::unique_ptr<AbstractClass> c = obj->methodFromOtherClass();
...
Your basic problem (as the warning told you) is that your function is returning the address of a local variable, and that local variable ceases to exist when the function returns.
Your first version can be changed to
AbstractClass* methodFromOtherClass()
{
if (somethingIsTrue)
{
Derived *d = new Derived();
return d;
}
SomeOtherDerived *s = new SomeOtherDerived();
return s;
}
Note that this requires the caller to delete the returned pointer when done.
The second version can be changed to
std::unique_ptr<AbstractClass> methodFromOtherClass()
{
if (somethingIsTrue)
{
Derived *d = new Derived();
return d;
}
SomeOtherDerived *s = new SomeOtherDerived();
return s;
}
which releases the caller from the obligation of releasing the dynamically allocated object.
In both cases, AbstractClass will need a virtual destructor, to avoid undefined behaviour when releasing the returned object.
Your underlying problem is that you're thinking in terms of how Java works, and C++ works very differently from Java in this regard. Stop trying to learn C++ by analogy with Java - in cases like this, you will make more trouble for yourself than it is worth. From a C++ perspective, Java blends the concepts of pointers and references into one thing, so working with C++ pointers and references like you would in Java is a recipe for trouble in C++.
I've stared using smart pointer and trying to wrap my head around best uses for it. I've read plenty of articles but I'm confused on which to use in the following example. I've included a shared_ptr and unique_ptrexamples to show what I'm trying to accomplish:
class A
public:
A();
private:
unique_ptr<B> ptrB;
unique_ptr<SomeObject> ptrUnique;
shared_ptr<SomeObject> ptrShared;
A::A()
{
ptrB(new B());
ptrUnique(new SomeObject());
ptrB->PassUnique(ptrUnique);
ptrShared(new SomeObject());
ptrB->PassShared(ptrShared);
}
class B:
public:
void PassUnique(unique_ptr<SomeObject> &ptr_unique);
void PassShared(weak_ptr<SomeObject> &ptr_weak);
void DoSomething();
private:
unique_ptr<SomeObject> ptrUnique;
weak_ptr<SomeObject> ptrWeak;
B::PassUnique(unique_ptr<SomeObject> &ptr_unique)
{
ptrUnique = ptr_unique;
}
B::PassShared(weak_ptr<SomeObject> &ptr_weak)
{
ptrWeak = ptr_weak;
}
B::DoSomething()
{
ptrUnique->SomeMethod();
shared_ptr<SomeObject> ptr1 = ptrWeak.lock();
ptr1->SomeMethod();
}
SomeObject class can be any class. A good example is a database handle that I pass from the parent class A were it was originally initiated to multiple class like B. And from B to C if it exists. My question is if I'm passing a unique_ptr as a reference will setting for example ptrUnqiue = ptr_unique in B:PassUnique create a copy which then is not correct? Or should this be done via shared_ptr? This understanding is what is confusing with smart pointers for me and would appreciate clarification.
Well, this is a question of lifetime. Do you need SomeObject to outlive A? Do B send or is being use outside of this context? You have to decide when your objects dies. If you think SomeObject exists only in this context, I would recommend A to be the owner, as it allocate the resource, and be to old a raw pointer to SomeObject. I would look like this:
class A
public:
A();
private:
unique_ptr<B> ptrB;
unique_ptr<SomeObject> ptrUnique;
};
A::A()
{
ptrB(new B());
ptrUnique(new SomeObject());
ptrB->PassUnique(*ptrUnique);
}
class B:
pubic:
void PassUnique(SomeObject& obj);
void DoSomething();
private:
SomeObject* ptrUnique;
};
B::PassUnique(SomeObject& obj)
{
ptrUnique = &obj;
}
B::DoSomething()
{
ptrUnique->SomeMethod();
}
There is no such thing as
ptrUnique = ptr_unique;
If you need SomeObject to be used and owned outside of this structure, then go with std::shared_ptr like you did. There were no errors with your std::shared_ptr code.
Answer is basically what would be a lifetime of the pointer in the A, B and/or C. Think of it as ranges, [A...a), [B...b) and [C...c). If [B...b) is always within [A...a) and [C...c) is always within [B...b), they have like a Russian dolls hierarchy, then passing down ref-to-ptr is ok. If ranges overlap and changes wildly so you don't really control where last ptr will be destructed and object will be deleted, you'd have to go with shared_ptr.