c++ - How can I delete a undeclared pointer? - c++

If the new operator was written in a function argument or constructor argument like:
Foo* f = new Foo(new Baz(0, 0));
// how to delete "new Baz(0, 0)"?
delete f;
I know it can be written to:
Baz* b = new Baz(0, 0)
Foo* f = new Foo(b);
delete b;
delete f;
But it became complicated, is there any better way?
Should I do something like this:
Class Foo {
private:
Baz* _b;
public:
Foo(Baz* b) : _b(b) {}
~Foo() {
delete _b;
}
}
// so that when I delete foo will also delete baz;

Following my own recommendation about the rule of zero and using std::unique_ptr, I would do something like this:
class Foo
{
public:
Foo(int a, int b)
baz_{ std::make_unique<Baz>(a, b) }
{
}
private:
std::unique_ptr<Baz> baz_;
};
And
auto foo = std::make_unique<Foo>(0, 0);
With this the foo object own its own unique Baz object.
If you want Foo to by copyable then use std::shared_ptr and std::make_shared instead.

More or less Yes, you should delete an allocated field in the destructor.
If the class has children, make the destructor virtual.
However you could have passed an existing pointer. And then the field is not owned.
You can use one of the ptr classes, i.e. std::unique_ptr for the Baz.
Or defer the deletion to the caller in some form:
Baz* _b; // Or Baz _b.
Foo(const Baz& b) : _b(new Baz(b)) {} // When feasible a copy.
From design point it would

Related

Lifetime of dependent classses in C++?

I have a class A that provides methods to construct instances of class B. And B holds a private reference to A and provides a constructor to set this reference.
class A {
public:
B* construct_B ();
}
class B {
private:
const A& private_A;
public:
B ( const A& my_A ): private_A (my_A) { }
}
The implementation of construct_B takes care of dynamic allocation and passing the reference to itself via this.
How do I implement this setup in such a way that I make sure that the lifetime of A is longer than B so that its reference remains valid? Notice that I don't care about all the possibilities of construct_B instead of returning a raw pointer I could return a smart pointer or similar.
One possible way of solving this could be having B instead of holding a reference to hold a smart pointer to A, and instead of dynamically allocating B in construct_B to take a static reference to B and then set it's pointer, something like
class A :
public std::enable_shared_from_this<A> {
public:
void setup_B ( const B& my_B ) {
my_B.set_A (shared_ptr_from_this() ) ;
}
class B {
private:
const shared_ptr<A> private_A_ptr;
public:
void set_A ( const shared_ptr<A> my_A ):
private_A_ptr (my_A) { }
}
which then could be implemented by
int main () {
A static_A;
B static_B;
A.setup_B (static_B);
}
Does the shared_ptr of this last construction avoid the problem of A being deleted before B?
shared_ptr is your answer. Something like this:
#include <memory>
struct A;
class B {
const std::shared_ptr<A> private_A_ptr;
public:
B(std::shared_ptr<A> parent) : private_A_ptr(std::move(parent)) {}
};
struct A :
std::enable_shared_from_this<A>
{
B make_b() {
return B(shared_from_this());
}
};
int main()
{
// this would be invalid:
//A a;
//auto b = a.make_b();
// but this is fine
auto pa = std::make_shared<A>();
auto b = pa->make_b();
// later...
pa.reset();
// A still exists because ownership was shared with b
}

pointer to an object has no any value (or do not get a value)

i have a problem with output of 2 classes like below:
foo.h
public:
Foo(){} ;
Foo(string);
Foo(const Foo&);
string getFooName() const;
~Foo();
private:
string foo;
Foo.cpp
Foo::Foo(string n):foo(n){
}
Foo::Foo(const Foo &f):foo(f.foo){
}
string Foo::getFooName() const{
return foo;
}
Foo::~Foo(){
}
and class Bar:
Bar.h
public:
Bar();
Bar(string, Foo&);
Bar(const Bar&);
Foo& getFoo() const;
~Bar();
private:
string bar;
Foo* foo;
};
Bar.cpp
Bar::Bar(string b, Foo &f):bar(b), foo(new Foo()){
}
Bar::Bar(const Bar &b):bar(b.bar), foo(new Foo(*b.foo)){
}
Foo &Bar::getFoo() const{
return *foo;
}
Bar::~Bar()
{
delete foo;
}
and in main fuction, when i use this cout<<"Test:"<<b->getFoo().getFooName(); it only gets me in output only Test: instead of Test:TestFoo.
what is wrong in my code? (gcc5.4.0,cmake 3.5.1)
tnx
and main.cpp
Foo* f;
Bar* b;
f=new Foo("TestFoo");
b=new Bar("TestBar",*f);
cout<<"Test:"<<b->getFoo().getFooName(); // this line
Bar::Bar(string b, Foo &f):bar(b), foo(new Foo()){}
Parameter f is unused. You need pass it to the Foo constructor.
Bar::Bar(string b, Foo &f):bar(b), foo(new Foo(f)){}
The issue lies in Bar.cpp:
The first constructor for Bar is
Bar::Bar(string b, Foo &f):bar(b), foo(new Foo()){
}
This tells the compiler to create a pointer to a new Foo object to store in the Bar object. However, new Foo object has nothing to do with the Foo object passed as input to the constructor. The constructor needs to use the Foo object passed as an input so that the new Foo object has the same value in the member variable foo:
Bar::Bar(string b, Foo &f):bar(b), foo(new Foo(f.foo)){
}
Then, the constructor call
b=new Bar("TestBar",*f);
in main.cpp will actually assign the member variable foo a value of "TestFoo" (whereas before it was not initializing the variable).
As a result, b->getFoo().getFooName() should return "TestFoo" as desired.
When you call
b = new Bar("TestBar", *f);
the following constructor is called:
Bar::Bar(string b, Foo &f):bar(b), foo(new Foo())
As you can see, the second parameter is not used to initialize the foo member, but a new one created instead. Its not the same object which you initialized with the "TestFoo"!
So when you print, "TestFoo" is not returned at all.

Passing object by unique_ptr or by value and how to implement

I have a case that I am not sure if I should use unique_ptr or pass Object by values.
Say that I have class A which has a vector Of class B and Class C has a vector of class B as well. Every time I am adding a B Object to Vector in class C it should be Removed from vector of Class C and vice versa. When Object C is destroyed all the objects in B Vector class should be add to B vector in class A
class B {
public:
B();
virtual ~B();
};
class A {
C & c;
std::vector<B> bs;
public:
A(C & c ): c(c){};
virtual ~A();
void add(B b){
bs.push_back(b);
c.remove(b);
}
void remove(B b){
bs.erase(std::remove(bs.begin(), bs.end(), b), bs.end());
}
};
class C {
public:
A & a;
std::vector<B> bs;
C(A & a): a(a) {
};
virtual ~C(){
for (B b : bs) {
a.add(b);
remove(b);
}
}
void add(B b){
bs.push_back(b);
a.remove(b);
}
void remove(B b){
bs.erase(std::remove(bs.begin(), bs.end(), b), bs.end());
}
};
My questions:
Is it better to use pointers in this case? I should always have a unique Object for B! In other words if content of two b objects are different they are still different because different address in memory.
I want to write this code with help of smart_pointers in C++ 11! Which type is better shared_ptr or unique_ptr? A B object is never owned by two objects and it has always one owner so I guess unique_ptr is better but I am not sure.
How Can I write the code above using unique_ptr?
If copy-constructing B is costly, then (smart)pointers are probably a good idea (redesigning the application logic might be another solution),
If I understood correctly, a given B instance is always manipulated by a single owner (either A or C). std::unique_ptr is therefore a reasonable choice,
Try the following implementation. I haven't compiled it but I think you'll get the general idea :)
.
class B {
public:
B();
virtual ~B();
};
class A {
C & c;
std::vector<std::unique_ptr<B>> bs;
public:
A(C & c ): c(c){};
virtual ~A();
// http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/
// (c) Passing unique_ptr by value means "sink."
void add(std::unique_ptr<B> b){
c.remove(b); // release the poiner from the other container
bs.emplace_back(b.get()); // emplace the pointer in the new one
b.release(); // emplacement successful. release the pointer
}
// http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/
// (d) Passing unique_ptr by reference is for in/out unique_ptr parameters.
void remove(std::unique_ptr<B>& b){
// #todo check that ther returned pointer is != bs.end()
std::find(bs.begin(), bs.end(), b)->release(); // first release the pointer
bs.erase(std::remove(bs.begin(), bs.end(), b), bs.end()); // then destroy its owner
}
};
class C {
public:
A & a;
std::vector<std::unique_ptr<B>> bs;
C(A & a): a(a) {
};
virtual ~C(){
for (auto&& b : bs) {
a.add(b);
// a is going to call this->remove()...
// unless calling this->remove() from "a"
// while this is being destroyed is Undefined Behavior (tm)
// I'm not sure :)
}
}
// http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/
// (c) Passing unique_ptr by value means "sink."
void add(std::unique_ptr<B> b){
c.remove(b); // release the poiner from the other container
bs.emplace_back(b.get()); // emplace the pointer in the new one
b.release(); // emplacement successful. release the pointer
}
// http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/
// (d) Passing unique_ptr by reference is for in/out unique_ptr parameters.
void remove(std::unique_ptr<B>& b){
// #todo check that ther returned pointer is != bs.end()
std::find(bs.begin(), bs.end(), b)->release(); // first release the pointer
bs.erase(std::remove(bs.begin(), bs.end(), b), bs.end()); // then destroy its owner
}
};
I would only use unique_ptr if you have to. You may prefer to make B a move-only type (like unique_ptr) to restrict ownership.
If B is expensive to move or it is not practical to prevent the copying of B then use unique_ptr but be aware that you are then paying for a dynamic memory allocation.
Here is how you could use a move-only B in an example inspired by your code. If you use unique_ptr instead it should work exactly the same:
struct B {
B();
B(B&&) = default; // Explicitly default the
B& operator=(B&&) = default; // move functions.
B(const B&) = delete; // Delete copy functions - Not strictly
B& operator=(const B&) = delete; // necessary but just to be explicit.
};
struct A {
std::vector<B> bs;
void add(B b){
bs.push_back(std::move(b));
}
B remove(std::vector<B>::iterator itr){
B tmp = std::move(*itr);
bs.erase(itr);
return tmp;
}
};
struct C {
A& a;
std::vector<B> bs;
C(A& a) : a(a) {}
~C(){
for (auto& b : bs) {
a.add(std::move(b));
}
} // bs will be deleted now anyway, no need to remove the dead objects
void add(B b){
bs.push_back(std::move(b));
}
B remove(std::vector<B>::iterator itr){
auto tmp = std::move(*itr);
bs.erase(itr);
return tmp;
}
};
int main() {
A a;
C c(a);
a.add(B());
auto tmp = a.remove(a.bs.begin());
c.add(std::move(tmp));
}
Live demo.

Whose responsibility is it to delete

In C++, whose responsibility is it to delete members of a class: the class, or the creator of an instance of that class?
For example, in the following code:
class B {
public:
B(int x) { num = x; }
int num;
};
class A {
public:
A(B* o) { obj = o; }
B* obj;
};
int main(void) {
A myA(new B(3));
return 0;
}
Should main delete the instance of B, or should A's destructor delete its local variable obj? Is this true in most cases, and in which cases if any is it not?
This is a basic question of ownership. If every A should own a B (as in, there should be a new B created when the A is created, that should also be destroyed be the A is destroyed, then you'd normally make A responsible for creating and destroying the instance of B:
class B {
int num;
public:
B(int x) : num(x) {}
};
class A {
B *obj;
public:
A(int value) : obj(new B(value)) {}
~A() { delete B; }
};
In such a case, however, chances are pretty good that A should just be written like:
class A {
B obj;
public:
A(int v) : obj(v) {}
};
int main() {
A a(3);
return 0;
}
This way, the instance of B will be created and destroyed automatically, without any intervention on your part at all.
Almost always A should manage it's members as this is what RAII is based off of. Use unique_ptr when you can.
If it doesn't manage it's data then it should use a different smart pointer, specifically shared_ptr. This shifts the responsibility to the shared_ptr, which is much less error prone than a vanilla pointer.
And of course, the preferred way is to use no pointers at all. Why are you calling new in the first place?

vector related memory allocation question

I am encountering the following bug.
I have a class Foo . Instances of this class are stored in a std::vector vec of class B.
in class Foo, I am creating an instance of class A by allocating memory using new and deleting that object in ~Foo().
the code compiles, but I get a crash at the runtime. If I disable delete my_a from desstructor of class Foo. The code runs fine (but there is going to be a memory leak).
Could someone please explain what is going wrong here and suggest a fix?
thank you!
class A{
public:
A(int val);
~A(){};
int val_a;
};
A::A(int val){
val_a = val;
};
class Foo {
public:
Foo();
~Foo();
void createA();
A* my_a;
};
Foo::Foo(){
createA();
};
void Foo::createA(){
my_a = new A(20);
};
Foo::~Foo(){
delete my_a;
};
class B {
public:
vector<Foo> vec;
void createFoo();
B(){};
~B(){};
};
void B::createFoo(){
vec.push_back(Foo());
};
int main(){
B b;
int i =0;
for (i = 0; i < 5; i ++){
std::cout<<"\n creating Foo";
b.createFoo();
std::cout<<"\n Foo created";
}
std::cout<<"\nDone with Foo creation";
std::cout << "\nPress RETURN to continue...";
std::cin.get();
return 0;
}
You need to implement a copy constructor and an assignment operator for Foo. Whenever you find you need a destructor, you alnmost certainly need these two as well. They are used in many places, specifically for putting objects into Standard Library containers.
The copy constructor should look like this:
Foo :: Foo( const Foo & f ) : my_a( new A( * f.my_a ) ) {
}
and the assignment operator:
Foo & Foo :: operator=( const Foo & f ) {
delete my_a;
my_a = new A( * f.my_a );
return * this;
}
Or better still, don't create the A instance in the Foo class dynamically:
class Foo {
public:
Foo();
~Foo();
void createA();
A my_a;
};
Foo::Foo() : my_a( 20 ) {
};
If you don't specify a copy constructor, the compiler makes one for you. Your compiler-generated copy constructor looks like this:
Foo::Foo(const Foo& copy)
: my_a(copy.my_a)
{}
Woops! You're copying just the pointer but not the pointed-to memory. Both your temporary Foo() in createFoo() and the one copied in to the vector point to the same memory, so the memory is deleted twice, which crashes your program on the second delete.
You should create a copy constructor that looks something like this:
Foo::Foo(const Foo& copy)
: my_a(new A(*copy.my_a))
{}
Note this crashes if copy has a NULL my_a member, and it also invokes the copy constructor on A, which you haven't specified either. So you'll want to make some further changes. You'll also want an operator= overload too.
The Foo object is copied and at the destruction of every copy, delete is called on the same pointer value my_a.
Implement the copy and assignment operator for Foo or use a smart pointer.
Foo( const Foo& s) : my_a( s.my_a ? new A(*s.my_a) : 0) {
}
Foo& operator= (const Foo& s) {
Foo temp(s);
temp.swap (*this);
return *this;
}
void swap (Foo &s) {
std::swap (my_a, s.my_a);
};