【问题标题】:Compile error when try to create singleton using shared_ptr尝试使用 shared_ptr 创建单例时编译错误
【发布时间】:2019-12-08 16:02:22
【问题描述】:

我尝试使用 shared_ptrs 创建一个单例对象。但是,当构造函数/析构函数对于特定对象是私有的时,代码不会编译 代码如下。h

//ThreadPool.h
class ThreadPool
{
  public:
  static std::shared_ptr<ThreadPool> & getInstance();
  inline static std::shared_ptr<ThreadPool> m_threadPoolInstance;
  private:
  ThreadPool() =default;
~ ThreadPool() = default;
  ThreadPool(ThreadPool const  &) = default;
 };
 //ThreadPool.cpp
#include "pch.h"
#include <ThreadPool.h>

std::shared_ptr<ThreadPool> & ThreadPool::getInstance()
{
    if (! m_threadPoolInstance)
    {
        ThreadPool * p_ThreadPool = new ThreadPool();
        m_threadPoolInstance.reset(p_ThreadPool);
    }
    return m_threadPoolInstance;
}

我正在使用 VS17 编译器 创建的错误如下

错误 C2440:“”:无法从“_Ux *”转换为 'std::shared_ptr' 和 [ _Ux=线程池 ] include\memory(1462):注意:没有构造函数可以采用源类型,或者构造函数重载决议不明确 threadpool.cpp(9):注意:参见函数模板的参考 实例化 'void std::shared_ptr::reset(_Ux *)' 正在编译 和 [ _Ux=线程池 ] threadpool.cpp(9): 注意: 参见函数模板实例化'void std::shared_ptr::reset(_Ux *)' 正在编译 和 [ _Ux=线程池 ]

当我在公共部分设置构造函数/析构函数时,编译成功。

但是使用 gcc 编译器运行相同的代码,编译成功

【问题讨论】:

  • 这里不需要共享指针。
  • ...因为共享指针的全部意义在于在不再需要对象时释放它。但这对于单例对象来说从来都不是问题。
  • 这是真的,但问题仍然存在。为什么用VS2017编译不了

标签: multithreading c++17 threadpool shared-ptr


【解决方案1】:

转换失败,因为您的 ThreadPool 类有一个私有析构函数。

调用.reset(ptr) 将使用删除表达式 (delete ptr;) 作为删除器,这要求析构函数是公共的。

这里参考重载(2):https://en.cppreference.com/w/cpp/memory/shared_ptr/reset

2-4) 将托管对象替换为 ptr 指向的对象。 Y 必须是完整类型并且可以隐式转换为 T。另外:

2) 使用删除表达式作为删除器。必须有一个有效的删除表达式, 即删除 ptr 必须格式正确、行为明确且不抛出任何异常。等价于 shared_ptr(ptr).swap(*this);。

您要么需要公开析构函数,要么提供自定义删除器。

【讨论】:

  • @getsoubl 我在使用 GCC 9.1 时遇到了同样的错误。你能用你正在使用的 GCC 的确切版本更新你的问题吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-14
  • 2012-11-19
  • 1970-01-01
  • 2022-10-18
  • 1970-01-01
  • 2016-12-27
  • 1970-01-01
相关资源
最近更新 更多