Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to safely destruct class with smart pointer to incomplete object type?

Tags:

c++

I'm concerned about using an incomplete type with a smart pointer and how the pointer is deleted. Is the following code safe? I don't think it would be, as main.cpp would generate Farm's default destructor which wouldn't see the complete type. To make it safe, I think I should create a non-inline destructor which sees the complete type. Is that correct?

Also is it the same if I used std::vector<Cow> in Farm instead?

farm.h

class Cow;

struct Farm
{
    Farm();
    // ~Farm();
    std::unique_ptr<Cow> cow;
};

farm.cpp

#include "cow.h"
// cow now complete

Farm::Farm()
{
    cow.reset(new Cow);
}

// Farm::~Farm() {}

main.cpp

#include "farm.h"

int main()
{
    Farm farm;
}

Edit: I tried to compile with Visual Studio without the destructor and it says error C2338: can't delete an incomplete type. I guess that answers my question.

like image 926
Neil Kirk Avatar asked Sep 01 '13 15:09

Neil Kirk


Video Answer


1 Answers

I don't think your code should compile (and it doesn't in gcc)

std::unique_ptr<Cow> uses std::default_delete<Cow>, and std::default_delete<Cow>::operator() should fail to instantiate for an incomplete type Cow.

See also Is it true that a unique_ptr declaration, unlike a auto_ptr declaration, is well-defined when its template type is of an incomplete type?

So you're right: you need to ensure that default_delete<Cow>::operator() is instantiated somewhere that the Cow type is complete. Which means the destructor of Farm needs to be defined in such a place.

I've just noticed that your subject says "smart pointer", while the question specifies unique_ptr. The answer would be different for a shared_ptr, since std::shared_ptr<Cow>::reset() is a function template that captures the (static) type of the pointer passed to it and stores a deleter. So with shared_ptr all you need is that the call to reset has the complete type Cow -- the location of the destructor doesn't matter.

like image 154
Steve Jessop Avatar answered Sep 30 '22 16:09

Steve Jessop