1

I am pretty new to C++ and have a problem regarding pointers/references. The following example reflects my problem:

#include <iostream> #include "boost/make_shared.hpp" #include "boost/utility.hpp" class UsedObjectInterface { public: virtual int data() const = 0; }; class UsedObject : public UsedObjectInterface { public: UsedObject() : data_(42) { } explicit UsedObject(int value) : data_(value) { } int data() const { return data_; } private: const int data_; }; class BaseClient : private boost::noncopyable { public: virtual const UsedObjectInterface& used_object() const = 0; }; class SegmentationFaultClient : public BaseClient { public: // This can't work, since the object is deleted immediately. // IMHO only the following two solutions can work: // 1. The member attribute is not a reference (not possible with an abstract class, we lose the advantages of polymorphism). // 2. The member attribute is a pointer. SegmentationFaultClient() : used_object_(UsedObject()) { } explicit SegmentationFaultClient(const UsedObjectInterface& used_object) : used_object_(used_object) { } const UsedObjectInterface& used_object() const { return this->used_object_; } private: const UsedObjectInterface& used_object_; }; class CorrectClient : public BaseClient { public: CorrectClient() : used_object_(boost::make_shared<UsedObject>()) { } explicit CorrectClient(const boost::shared_ptr<UsedObjectInterface> used_object) : used_object_(used_object) { } // TODO Is it possible to change this to a const&, so at least the interface // is the same as in SegmentationFaultClient? Then the above constructor can // be deleted. explicit CorrectClient(const UsedObjectInterface& used_object) : used_object_(&used_object) { // TODO How-to convert a raw pointer to a smart pointer? } const UsedObjectInterface& used_object() const { return *this->used_object_; } private: const boost::shared_ptr<UsedObjectInterface> used_object_; }; int main() { SegmentationFaultClient segfault_client; const UsedObjectInterface& a = segfault_client.used_object(); std::cout << a.data() << std::endl; // Correct, but how to make this work with a const& constructor? const UsedObject first_object; CorrectClient correct_client(first_object); const UsedObjectInterface& b = correct_client.used_object(); std::cout << b.data() << std::endl; } 

As the comments say, the implementaton of the SegmentationFaultClient class is simply wrong, since the default constructor creates an object on the stack, which is "immediately" removed. Therefore I came up with the class CorrectClient, which uses pointers. My goal is to keep the nice API (no public Boost) from SegmentationFaultClient (const& default constructor). The above example does not work and terminates with the following error:

invalid conversion from 'const UsedObjectInterface*' to 'boost::shared_ptr<UsedObjectInterface>::element_type* {aka UsedObjectInterface*}' [-fpermissive] explicit shared_ptr( Y * p ): px( p ), pn() // Y must be complete 

So my question is: Is it possible to convert a raw pointer * to a smart pointer? If so, what is the best way to do that? If you see any other problems with my code, please let me know, too!

1 Answer 1

2

Problem is, that you are trying to convert const-pointer to a non-const pointer. You can use reference as param, instead of const-reference, or you can do following

const boost::shared_ptr<const UsedObjectInterface> used_object_; 

However, default-deleter for shared_ptr will be delete pointer, that is in your case not allocated on heap. You should point empty-deleter, or not use shared_ptr in this case.

Sign up to request clarification or add additional context in comments.

3 Comments

Wow, what a stupid mistake from me. Yeah, I only made the smart pointer const and not the actual object. Thank you for your hint! I do not fully understand your last sentence, what do you mean with "point empty-deleter"? Can you provide me with further information?
@FlorianWolters boost.org/doc/libs/1_54_0/libs/smart_ptr/shared_ptr.htm use of constructor with deleter, which is function, that do nothing.
Btw, what is your recommendation to deal with such a situation? Both approaches would create "raw-pointer" behavior imo. I want both a default constructor and a complete constructor. The default constructor should create an instance of another class, whereas the complete constructor takes one argument of the same class. Are there any "best-practice" C++ memory ownership approaches?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.