【问题标题】:Create smart pointer from raw pointer / reference从原始指针/引用创建智能指针
【发布时间】:2013-11-26 11:28:07
【问题描述】:

我对 C++ 还很陌生,并且对指针/引用有疑问。下面的例子反映了我的问题:

#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;
}

正如 cmets 所说,SegmentationFaultClient 类的实现是完全错误的,因为默认构造函数在堆栈上创建了一个对象,该对象被“立即”删除。因此我想出了使用指针的类CorrectClient。我的目标是保留来自SegmentationFaultClientconst&amp; 默认构造函数)的漂亮 API(无公共 Boost)。上面的示例不起作用并以以下错误终止:

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

所以我的问题是:是否可以将原始指针 * 转换为智能指针?如果是这样,最好的方法是什么?如果您发现我的代码有任何其他问题,也请告诉我!

【问题讨论】:

    标签: c++ pointers boost reference smart-pointers


    【解决方案1】:

    问题是,您正在尝试将const-pointer 转换为non-const pointer。您可以使用reference 作为参数,而不是const-reference,或者您可以执行以下操作

    const boost::shared_ptr<const UsedObjectInterface> used_object_;
    

    但是,shared_ptr 的默认删除器将是 delete 指针,在您的情况下,这不是在堆上分配的。你应该指向empty-deleter,或者在这种情况下不要使用shared_ptr

    【讨论】:

    • 哇,我犯了一个多么愚蠢的错误。是的,我只制作了智能指针const,而不是实际的对象。谢谢你的提示!我不完全理解你的最后一句话,“点empty-deleter”是什么意思?您能提供更多信息吗?
    • @FlorianWolters boost.org/doc/libs/1_54_0/libs/smart_ptr/shared_ptr.htm 使用带有删除器的构造函数,它是函数,什么都不做。
    • 顺便说一句,您对处理这种情况有什么建议?这两种方法都会创建“原始指针”行为 imo。我想要一个默认构造函数和一个完整的构造函数。默认构造函数应该创建另一个类的实例,而完整的构造函数接受同一类的一个参数。是否有任何“最佳实践”C++ 内存所有权方法?
    猜你喜欢
    • 2016-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-25
    • 2022-01-23
    相关资源
    最近更新 更多