智能指针 -- unique_ptr

2023-11-19

源码分析

源码链接: gcc/unique_ptr.h at master · gcc-mirror/gcc · GitHub

上面链接中的源码是unique_ptr的完整定义,我们来简化其类结构看看:

template <typename _Tp, typename _Dp = default_delete<_Tp>>
class unique_ptr
{
  __uniq_ptr_data<_Tp, _Dp> _M_t;

  public:
    using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer;
    using element_type  = _Tp;
    using deleter_type  = _Dp;

    //构造函数
    template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
	constexpr unique_ptr() noexcept: _M_t() { }
    
    template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
    unique_ptr(pointer __p) noexcept : _M_t(__p) { }

    template<typename _Del = deleter_type,typename = _Require<is_copy_constructible<_Del>>>
    unique_ptr(pointer __p, const deleter_type& __d) noexcept : _M_t(__p, __d) {  }

    template<typename _Del = deleter_type, typename = _Require<is_move_constructible<_Del>>>
    unique_ptr(pointer __p,__enable_if_t<!is_lvalue_reference<_Del>::value,_Del&&> __d) 
    noexcept : _M_t(__p, std::move(__d)) { }

    template<typename _Del = deleter_type,typename _DelUnref = typename remove_reference<_Del>::type>
    unique_ptr(pointer,__enable_if_t<is_lvalue_reference<_Del>::value, _DelUnref&&>) = delete;

	constexpr unique_ptr(nullptr_t) noexcept : _M_t() { }

    // 移动构造函数
    unique_ptr(unique_ptr&&) = default;

    unique_ptr(unique_ptr<_Up, _Ep>&& __u) 
    noexcept : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) {  }

    // 析构函数
    ~unique_ptr() noexcept {
	  auto& __ptr = _M_t._M_ptr();
	  if (__ptr != nullptr)
	    get_deleter()(std::move(__ptr));
	    __ptr = pointer();
    }

    // 操作符 = 
    unique_ptr& operator=(unique_ptr&&) = default;

    template<typename _Up, typename _Ep>
    typename enable_if< __and_<__safe_conversion_up<_Up, _Ep>,is_assignable<deleter_type&, _Ep&&>>::value,unique_ptr&>::type
    operator=(unique_ptr<_Up, _Ep>&& __u) noexcept {
	  reset(__u.release());
	  get_deleter() = std::forward<_Ep>(__u.get_deleter());
	  return *this;
    }

  unique_ptr& operator=(nullptr_t) noexcept {
	 reset();
	 return *this;
  }
  
  //操作符 *
  typename add_lvalue_reference<element_type>::type
  operator*() const noexcept(noexcept(*std::declval<pointer>())) {
	  return *get();
  }
  
  //操作符 ->
  pointer operator->() const noexcept {
	  _GLIBCXX_DEBUG_PEDASSERT(get() != pointer());
	  return get();
  }

  // 获取指针
  pointer get() const noexcept
  { return _M_t._M_ptr(); }

  // 获取deleter函数
  deleter_type& get_deleter() noexcept
  { return _M_t._M_deleter(); }
   
  const deleter_type& get_deleter() const noexcept { 
      return _M_t._M_deleter(); 
  }

  // 操作符 取bool
  explicit operator bool() const noexcept { 
       return get() == pointer() ? false : true; 
  }
  // release接口
  pointer release() noexcept { return _M_t.release(); }
  //reset接口
  void reset(pointer __p = pointer()) noexcept {
	 _M_t.reset(std::move(__p));
  }
  //swap接口
  void swap(unique_ptr& __u) noexcept {
	_M_t.swap(__u._M_t);
  }

   // 禁用从lvalue拷贝操作.
   unique_ptr(const unique_ptr&) = delete;
   unique_ptr& operator=(const unique_ptr&) = delete;
};

代码示例1

默认构造函数,操作符(), 以及get(),操作符->

#include <iostream>
#include<memory>
using namespace std;

class Car {
public:
    Car() {
        cout << "consutrct car" << endl;
    }
    virtual ~Car() {
        cout << "desconsturct car" << endl;
    }
    void ShowInfo() {
        cout << __func__ << ": this is base Car class" << endl;
    }

    void ShowInfoWithMember() {
        cout << __func__ << ": var_test_:" << var_test_;
    }
private:
    int var_test_ = 0;
};

int main() {
    std::unique_ptr<Car> aa;
    if (!aa) {
      cout << "aa is not nullptr" << endl;
    }

    if (!aa.get()) {
        cout << "aa.get() is not nullptr" << endl;
    }

    aa->ShowInfo();

    aa->ShowInfoWithMember()

}

示例运行结果:

 过程分析:

那么该示例实际都调用了unique_ptr这个类中的哪些接口呢 ?

默认构造函数

std::unique_ptr<Car> aa;

上述语句会调用unique_ptr的默认构造函数:

 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
 constexpr unique_ptr() noexcept : _M_t()  { }

可以看到class unique_ptr中有个成员_M_t:

template <typename _Tp, typename _Dp = default_delete<_Tp>>
class unique_ptr
{
   ..............;
   __uniq_ptr_data<_Tp, _Dp> _M_t;
   ..............;
};

template <typename _Tp, typename _Dp>
struct __uniq_ptr_data<_Tp, _Dp, true, false> : __uniq_ptr_impl<_Tp, _Dp>
{
   using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
   __uniq_ptr_data(__uniq_ptr_data&&) = default;
   __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete;
};

template <typename _Tp, typename _Dp>
class __uniq_ptr_impl
{
  template <typename _Up, typename _Ep, typename = void>
  struct _Ptr {
    using type = _Up*;
  };

  template <typename _Up, typename _Ep>
  struct _Ptr<_Up, _Ep, __void_t<typename remove_reference<_Ep>::type::pointer>>
  {
    using type = typename remove_reference<_Ep>::type::pointer;
  };

  public:
    using _DeleterConstraint =
      enable_if<__and_<__not_<is_pointer<_Dp>>,is_default_constructible<_Dp>>::value>;

    using pointer = typename _Ptr<_Tp, _Dp>::type;

    __uniq_ptr_impl() = default;
    __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; }

    template<typename _Del>
	__uniq_ptr_impl(pointer __p, _Del&& __d) : _M_t(__p, std::forward<_Del>(__d)) { }

    __uniq_ptr_impl(__uniq_ptr_impl&& __u) noexcept: _M_t(std::move(__u._M_t))
    { __u._M_ptr() = nullptr; }

    __uniq_ptr_impl& operator=(__uniq_ptr_impl&& __u) noexcept {
	  reset(__u.release());
	  _M_deleter() = std::forward<_Dp>(__u._M_deleter());
	  return *this;
    }

    pointer& _M_ptr() noexcept { return std::get<0>(_M_t); }
    pointer  _M_ptr() const noexcept { return std::get<0>(_M_t); }

    _Dp& _M_deleter() noexcept { return std::get<1>(_M_t); }
    const _Dp& _M_deleter() const noexcept { return std::get<1>(_M_t); }

    void reset(pointer __p) noexcept {
	  const pointer __old_p = _M_ptr();
	  _M_ptr() = __p;
	  if (__old_p)
	    _M_deleter()(__old_p);
    }

    pointer release() noexcept {
	  pointer __p = _M_ptr();
	  _M_ptr() = nullptr;
	  return __p;
    }

    void swap(__uniq_ptr_impl& __rhs) noexcept
    {
	  using std::swap;
	  swap(this->_M_ptr(), __rhs._M_ptr());
	  swap(this->_M_deleter(), __rhs._M_deleter());
    }

    private:
      tuple<pointer, _Dp> _M_t;
};

 通过上述代码可以看出unique_ptr() :: _M_t() 这个语句会调用到 __uniq_ptr_impl() = default; 而__uniq_ptr_impl中有一个成员:tuple<pointer, _Dp> _M_t;

操作符()

if (!aa.get()) {
        cout << "aa.get() is nullptr" << endl;
    }
 

上述语句会调用到unique_ptr::get()

  pointer get() const noexcept
  { return _M_t._M_ptr(); }

再调用到__uniq_ptr_impl::_M_ptr()

  pointer& _M_ptr() noexcept { return std::get<0>(_M_t); }
  pointer  _M_ptr() const noexcept { return std::get<0>(_M_t); }

最终取出的是tuple<pointer, _Dp> _M_t中的pointer这个指针,此例子中应该是Car* 类型,因为默认构造函数没有对tuple<pointer, _Dp> _M_t中的pointer这个指针赋值,所以unique_ptr::get()返回的就是空指针了。

操作符->

aa->ShowInfo();

上述代码实际上调用的是unique_ptr这个类中的操作符->

  pointer operator->() const noexcept {
	  _GLIBCXX_DEBUG_PEDASSERT(get() != pointer());
	  return get();
  }

然而此测试代码中unique_ptr.get() 返回的是空,那为什么调用ShowInfo()函数不会crash ?

而调用ShowInfoWithMember() 这个接口就crash了呢 ?

void Car::ShowInfoWithMember() {
        cout << __func__ << ": var_test_:" << var_test_;
}
aa->ShowInfoWithMember()

这篇博客就解释的很到位:C++---空指针能调用类成员函数吗?_shanghx_123的博客-CSDN博客_空指针调用成员函数

空指针为什么能调用成员函数?
对于类成员函数而言,并不是一个对象对应一个单独的成员函数体,而是此类的所有对象共用这个成员函数体。 当程序被编译之后,此成员函数地址即已确定。当调用p->func1(); 这句话时,其实就是调用A::func1(this);而成员函数的地址在编译时就已经确定, 需要注意的是,你用空指针调用成员函数,只是让this指针指向了空,所以空指针也是可以调用普通成员函数,只不过此时的this指针指向空而已,但函数fun1函数体内并没有用到this指针,所以不会出现问题。
当成员函数体内用到this指针时,如果你的this指针是空,那么程序就会崩溃。

代码示例2 

reset() , release()函数

class Car {
public:
    Car() {
        cout << "consutrct car" << endl;
    }
    virtual ~Car() {
        cout << "desconsturct car" << endl;
    }
    void ShowInfo(string ss) {
        cout << __func__ << "," << ss << endl;
    }
    void ShowInfoWithMember(string ss) {
        cout << __func__ << "," << ss << ", var_test_:" << var_test_ << endl;
    }
private:
    int var_test_ = 0;
};

auto DelCar = [] (Car *car) {
                  cout << "this is in DelCar function" << endl;
                  delete car;
              };

int main() {
    Car* pTest = new Car();
    std::unique_ptr<Car, decltype(DelCar)> aa(pTest, DelCar);
    if (aa.get()) {
        cout << "main: aa.get() is not nullptr" << endl;
    } else {
        cout << "main: aa.get() is nullptr" << endl;
    }
    aa->ShowInfo("aa");
    aa->ShowInfoWithMember("aa");

    std::unique_ptr<Car, decltype(DelCar)> bb(nullptr, DelCar);
    cout << "bb.reset" << endl;
    bb.reset(pTest);

    if (bb.get()) {
        cout << "main: bb.get() is not nullptr" << endl;
    } else {
        cout << "main: bb.get() is nullptr" << endl;
    }
    if (aa.get()) {
        cout << "main: aa.get() is not nullptr after reset bb" << endl;
    } else {
        cout << "main: aa.get() is nullptr after reset bb" << endl;
    }
    aa->ShowInfo("bb");
    aa->ShowInfoWithMember("bb");
}

代码运行结果:

 上述示例代码主要是示例带删除函数的unique_ptr的构造函数以及unique_ptr::reset()函数:

auto DelCar = [] (Car *car) {
                  cout << "this is in DelCar function" << endl;
                  delete car;
              };
Car* pTest = new Car();
std::unique_ptr<Car, decltype(DelCar)> aa(pTest, DelCar);

上面代码会调用的unique_ptr的构造函数: 

 template<typename _Del = deleter_type,
          typename = _Require<is_copy_constructible<_Del>>>
 unique_ptr(pointer __p, const deleter_type& __d) noexcept : _M_t(__p, __d) {  }

 reset函数

std::unique_ptr<Car, decltype(DelCar)> bb(nullptr, DelCar);
cout << "bb.reset" << endl;
bb.reset(pTest);

上述代码会调用到unique_ptr的reset函数:

  void reset(pointer __p = pointer()) noexcept {
	 _M_t.reset(std::move(__p));
  }

然后会调用到__uniq_ptr_impl::reset

tuple<pointer, _Dp> _M_t;
pointer& _M_ptr() noexcept { return std::get<0>(_M_t); }

void reset(pointer __p) noexcept {
	const pointer __old_p = _M_ptr();
	_M_ptr() = __p;
	if (__old_p)
	  _M_deleter()(__old_p);
}

通过__uniq_ptr_impl的reset函数源码可以知道,reset会先将old_ptr取出来,如果old_ptr不为空则向调用deleter所释放掉old_ptr, 然后将reset参数中新的ptr存入到tuple _M_t中。

使用pTest指针构造unique_ptr aa之后,再此使用pTest指针再构造一个unique_ptr bb会发生什么事情呢?

unique_ptr aa和bb 还是都在管理指针Car* pTest,并且都能正常访问pTest的成员函数和成员变量。只不过在aa析构的时候已经将pTest释放,而bb析构的时候再次释放pTest导致程序崩溃了。

 release()

那么上述代码,如何不让它崩溃呢 ?使用unique_ptr::release()

int main() {
    Car* pTest = new Car();
    std::unique_ptr<Car, decltype(DelCar)> aa(pTest, DelCar);

    ......................;
    aa->ShowInfo("aa");
    aa->ShowInfoWithMember("aa");

    std::unique_ptr<Car, decltype(DelCar)> bb(nullptr, DelCar);
    cout << "bb.reset" << endl;
    bb.reset(pTest);

    .......................;

    aa->ShowInfo("bb");
    aa->ShowInfoWithMember("bb");

    cout << "call aa.release()" << endl;
    aa.release();

}

程序运行结果:

将aa release一把后,程序就不会蹦了。

下面来看看release函数的实现:

pointer __uniq_ptr_impl::release() noexcept {
	  pointer __p = _M_ptr();
	  _M_ptr() = nullptr;
	  return __p;
}
pointer unique_ptr::release() noexcept { return _M_t.release(); }

 unique_ptr::release函数只是将unique_ptr中托管的指针置位nullptr,而不是像 unique_ptr::reset函数调用deleter将托管指针销毁。

unique_ptr拷贝构造函数和移动构造函数以及operator =

示例代码3

拷贝构造函数, operator =

class Car {
public:
    Car() {
        cout << "consutrct car" << endl;
    }
    virtual ~Car() {
        cout << "desconsturct car" << endl;
    }
    void ShowInfo(string ss) {
        cout << __func__ << "," << ss << endl;
    }
    void ShowInfoWithMember(string ss) {
        cout << __func__ << "," << ss << ", var_test_:" << var_test_ << endl;
    }
private:
    int var_test_ = 0;
};

void func(std::unique_ptr<Car> pp) {
    pp->ShowInfoWithMember("func_test");
}

unique_ptr<Car>  func2(std::unique_ptr<Car> &pp) {
  return pp;
}

int main() {
    Car* pTest = new Car();
    std::unique_ptr<Car> aa(pTest);
    //执行拷贝构造函数三种场景
    //1. 使用a对象初始化b对象
    std::unique_ptr<Car> bb(aa);

    //2. 函数参数
    func(aa); //aa 
    
    //3. 返回值
    unique_ptr cc = func2(aa);
    //上面这三种情况都会因调用拷贝构造函数,而编译报错
    
    std::unique_ptr<Car> bb(nullptr);
    bb = aa;  //会调用到operator = ,此处会编译报错
}

 从unique_ptr的定义来看,拷贝构造函数和operator = 是被删除禁用的。所以会编译失败。

  unique_ptr(const unique_ptr&) = delete;
  unique_ptr& operator=(const unique_ptr&) = delete;

移动构造函数和移动operator =

上面的代码编译错误如何修复呢 ?

int main() {
    Car* pTest = new Car();
    std::unique_ptr<Car> aa(pTest);
    // func(aa); //aa 作为函数参数,会调用到unique_ptr的拷贝构造函数,此时会编译报错
    func(std::move(aa));

    std::unique_ptr<Car> bb(nullptr);
    //bb = aa;  //会调用到operator = ,此处会编译报错
    bb = std::move(aa);
}

使用std::move(aa)之后将aa变成右值,编译就不会报错了。此时会调用unique_ptr中的以下函数:

template<typename _Up, 
         typename _Ep, 
         typename = _Require<__safe_conversion_up<_Up, _Ep>,
	                         __conditional_t<is_reference<_Dp>::value,
			                 is_same<_Ep, _Dp>,
			                 is_convertible<_Ep, _Dp>>>>
unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
	: _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
{ }


template<typename _Up, typename _Ep>
typename enable_if< __and_<__safe_conversion_up<_Up, _Ep>,
                                   is_assignable<deleter_type&, _Ep&&>
                                 >::value,unique_ptr&>::type
operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
{
   reset(__u.release());
   get_deleter() = std::forward<_Ep>(__u.get_deleter());
   return *this;
}

pointer __uniq_ptr_impl::release() noexcept {
	  pointer __p = _M_ptr();
	  _M_ptr() = nullptr;
	  return __p;
}

从上面的代码可以看出__u.release()将__u中托管的指针先取出来,然后置为nullptr,再return。也就是将托管的指针所有权进行了转移。

代码示例4

deleter

#include <iostream>
#include<memory>
using namespace std;
class Car;
auto DelCarLamda = [] (Car *car) {
                  cout << "this is in DelCar function" << endl;
                  delete car;
};
struct DelCarStruct {
  void operator() (Car *car) const {
    if (car != nullptr) {
        delete car;
    }
  }
};
typedef void (*DelCarFuncType)(Car*);

void DelCarFunc(Car *car) {
  if (car != nullptr) {
    delete car;
  }
}
int main() {
    // need the second param: deleter var
    std::unique_ptr<Car, decltype(DelCarLamda)> ll(new Car(), DelCarLamda);
    cout << "use Lamda deleter, size:" << sizeof(ll) << endl;

    // need the second param: deleter var
    // 此种方式,unique_ptr的size会多一个指针变量的大小
    std::unique_ptr<Car, DelCarFuncType> ff(new Car(), DelCarFunc);
    cout << "use func pointer deleter, size:" << sizeof(ff) << endl;

    // no need the second param
    std::unique_ptr<Car, DelCarStruct> ss(new Car());
    cout << "use struct operator () deleter, size:" << sizeof(ss) << endl;
}

class Car {
public:
    Car() {
        cout << "consutrct car" << endl;
    }
    virtual ~Car() {
        cout << "desconsturct car" << endl;
    }
    void ShowInfo(string ss) {
        cout << __func__ << "," << ss << endl;
    }
    void ShowInfoWithMember(string ss) {
        cout << __func__ << "," << ss << ", var_test_:" << var_test_ << endl;
    }
private:
    int var_test_ = 0;
};

代码运行结果:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

智能指针 -- unique_ptr 的相关文章

  • 有没有快速创建集合的方法?

    目前我正在创建一个像这样的新集 std set a s s insert a1 s insert a2 s insert a3 s insert a10 有没有办法创建s在一行 int myints 10 20 30 40 50 std s
  • 在实体框架拦截器中向 DbScanExpression 添加内部联接

    我正在尝试使用实体框架 CommandTree 拦截器通过 DbContext 向每个查询添加过滤器 为了简单起见 我有两个表 一个称为 User 有两列 UserId 和 EmailAddress 另一个称为 TenantUser 有两列
  • 在 C# 中按元素相乘数组具有意想不到的性能

    我想找到按元素相乘两个数组的最佳方法 这是更广泛项目的一部分 其中性能而不是唯一的考虑因素 我今天开始用 C Linqpad 编写一些函数 因此它还没有以任何方式进行优化 下面代码的输出如下 Environment ProcessorCou
  • 为什么在创建矩阵类时使用向量不好?

    对于我的矩阵类 我做了 template
  • 更改 Qt OpenGL 窗口示例以使用 OpenGL 3.3

    我正在尝试更改 Qt OpenGL 示例以使用更现代的 opengl 版本 330 似乎合适 所以我做了 在 main cpp 上设置版本和配置文件 设置着色器版本 更改着色器以使用统一 它现在构建没有任何错误 但我只看到一个空白窗口 我错
  • 如何在 SqlDataReader.Read() 期间从死锁异常中恢复

    我的 NET 应用程序的事件日志显示 它在从 Sql Server 读取数据时偶尔会出现死锁 这种情况通常非常罕见 因为我们已经优化了查询以避免死锁 但有时仍然会发生 过去 我们在调用ExecuteReader函数在我们的SqlComman
  • 指向特征矩阵的指针数组

    我在代码中使用 Eigen 的 MatrixXd 矩阵 在某个时刻我需要一个 3D 矩阵 由于 Eigen 没有三维矩阵类型 因为它仅针对线性代数进行了优化 因此我创建了一个 MatrixXd 类型的指针数组 Eigen MatrixXd
  • ASP.Net Core 内容配置附件/内联

    我正在从 WebAPI 控制器返回一个文件 Content Disposition 标头值自动设置为 附件 例如 处置 附件 文件名 30956 pdf 文件名 UTF 8 30956 pdf 当它设置为附件时 浏览器将要求保存文件而不是打
  • 动态生成的控件 ID 返回为 NULL

    我可以在 Page PreInit 函数中创建动态控件 如何检索控件及其 ID 我的 C 代码用于创建动态控件之一 var btn new WebForms Button btn Text btn ID Addmore btn Click
  • 单例模式和 std::unique_ptr

    std unique ptr唯一地控制它指向的对象 因此不使用引用计数 单例确保利用引用计数只能创建一个对象 那么会std unique ptr与单例执行相同 单例确保只有一个实例属于一种类型 A unique ptr确保只有一个智能指针到
  • 在 JSQMessagesViewController 中显示 LocationMediaItem

    我刚刚尝试实施LocationMediaItem in my Xamarin iOS应用程序使用JSQMessagesViewController 一切都很顺利 唯一的问题是UICollectionView应该显示位置的单元格永远停留在加载
  • 从 WebBrowser 控件 C# 获取滚动值

    我试图在 WebBrowser 控件中获取网页的 Y 滚动索引 但无法访问内置滚动条的值 有任何想法吗 对于标准模式下的 IE 使用文档类型 正如你所说 scrollTop是的财产元素 而不是 HtmlDocument htmlDoc th
  • Visual Studio Code:如何配置 includePath 以获得更好的 IntelliSense 结果

    我是使用 Visual Studio Code 的完全初学者 我不知道我在做什么 我已经四处搜索 也许还不够 但我找不到像我这样的人如何配置的简单解释c cpp properties json每当我单击带有绿色波浪线下划线的行旁边的黄色灯泡
  • 如何在标准 WPF ListView 中启用 UI 虚拟化

    我正在使用 NET 4 5 VS2012 并且我有一个 ListView 看起来像这样
  • 如何在c的case语句中使用省略号?

    CASE expr no commas ELLIPSIS expr no commas 我在c的语法规则中看到了这样的规则 但是当我尝试重现它时 int test float i switch i case 1 3 printf hi 它失
  • ASP.NET MailMessage.BodyEncoding 和 MailMessage.SubjectEncoding 默认值

    很简单的问题 但我在 MSDN 上找不到答案 查找 ASP NET 将用于的默认值 MailMessage BodyEncoding and MailMessage SubjectEncoding 如果你不在代码中设置它们 Thanks F
  • 跨多个域的 ASP.NET 会话

    是否有合适的 NET 解决方案来在多个域上提供持久服务器会话 即 如果该网站的用户在 www site1 com 下登录 他们也将在 www site2 com 下登录 安全是我们正在开发的程序的一个问题 Thanks 它是否需要在会话中
  • C++ Streambuf 方法可以抛出异常吗?

    我正在尝试找到一种方法来获取读取或写入流的字符数 即使存在错误并且读 写结束时间较短 该方法也是可靠的 我正在做这样的事情 return stream rdbuf gt sputn buffer buffer size 但如果streamb
  • 在简单注入器中解析具有自定义参数的类

    我正在使用以下命令创建 WPF MVVM 应用程序简易注射器作为 DI 容器 现在 当我尝试从简单注入器解析视图时遇到一些问题 因为我需要在构造时将参数传递到构造函数中 而不是在将视图注册到容器时 因此这不是适用的 简单注入器将值传递到构造
  • 使我的 COM 程序集调用异步

    我刚刚 赢得 了在当前工作中维护用 C 编码的遗留库的特权 这个dll 公开使用 Uniface 构建的大型遗留系统的方法 除了调用 COM 对象之外别无选择 充当此遗留系统与另一个系统的 API 之间的链接 在某些情况下 使用 WinFo

随机推荐

  • 计算机视觉之目标检测——R-CNN、Fast R-CNN和Faster R-CNN详解

    计算机视觉之目标检测 R CNN Fast R CNN和Faster R CNN详解 文章目录 计算机视觉之目标检测 R CNN Fast R CNN和Faster R CNN详解 目标检测的任务 目标检测的方法 R CNN Fast R
  • yagmail发送邮件

    分五步实现 1 导入yagmail第三方库 2 连接邮箱 3 添加邮件内容 4 发送邮件 5 释放邮箱 导入yagmail第三方库 import yagmail yagmail SMTP user 邮箱名 host SMTP服务器域名 ya
  • Vue 下拉框值变动事件传多个参数

    在使用 Vue 进行开发时 下拉框值变动事件 change 是很常用的 其传参一般分为两种方式 默认传参和自定义传参 默认传参 change 默认会传选中项标识的参数 在传参处不用定义 在方法中直接接受即可
  • Linux下的ssh

    SSH 为 Secure Shell 的缩写 由 IETF 的网络工作小组 Network Working Group 所制定 SSH 为建立在应用层和传输层基础上的安全协议 SSH 是目前较可靠 专为远程登录会话和其他网络服务提供安全性的
  • 将MindManager添加到鼠标右键新建项

    事情缘起于自己做事习惯为每个项目添加一个思维导图作为项目总看板 但每次都需要自己通过软件新建一个空白文件 再将空白文件索引到项目文件夹 再更名保存 虽然步骤不太多 但每次都需要这样的操作确实让我很困扰 所以就心想能不能让Mindmanage
  • ORM 的功能

    ORM要完成对象的初始化以及CRUD功能 在这些功能中尤其是query和update已经蕴含了相应的map的功能 除此之外还要提供transaction和concurrency的功能 这些基本的功能很好理解 不过相应的实现是比较复杂的 还要
  • 机器学习之朴素贝叶斯

    机器学习之朴素贝叶斯 1 朴素贝叶斯 2 朴素贝叶斯应用 3 代码实现贝努力朴素贝叶斯 4 代码实现高斯朴素贝叶斯 5 代码实现多项式朴素贝叶斯 6 总结 前言 主要介绍朴素贝叶斯的概念 公式 以及代码实现贝努利 高斯 多项式朴素贝叶斯 1
  • PyQt6 Designer与实际运行不一致问题

    我们在Designer设计布局时 会先定义好布局然后只在某个布局内存放元素 其他布局为空 可能就会产生布局不一致问题 其实已经存在了对应的布局只是里面为空 所以剩余空间优先被有元素的布局使用 我们在每个布局中加入某个组件即可解决
  • VC++ CMemDC类的扩展(新版)

    上一版本链接 https blog csdn net u012156872 article details 103755254 测试过程中发现存在问题 于是进行了功能补充 源码实现 CSWMemDC h pragma once namesp
  • vant + moment插件自定义count-down倒计时

    根据vant官网https vant ui github io vant v2 zh CN按需引入找到倒计时 自定义时间格式参考下图
  • matlab2016b版本安装

    安装包下载地址 链接 https pan baidu com s 1RrUp8TBIa7g7mhfSUtqAsg 提取码 foc1 1 解压文件包 2 在 matlab R2016b 64bit 文件下 找到 setup 文件 右击选择 以
  • 【C++】_5.模板

    目录 1 泛型编程 2 函数模板 2 1 概念 2 2 函数模板格式 2 3 函数模板原理 2 4 函数模板的实例化 2 5 函数模板的匹配原则 3 类模板 4 非类型模板参数 5 模板的特化 5 1 概念 5 2 函数模板特化 5 3 类
  • 解析request.getParameter() 和request.getAttribute() 区别

    一 request getParameter 和request getAttribute 区别 1 request getParameter 取得是通过容器的实现来取得通过类似post get等方式传入的数据 request setAttr
  • django高并发部署

    django高并发部署
  • React解密:React Hooks函数之useCallback和useMemo

    之所以将useCallback和useMemo放到一起 从某种意义上说 他们都是性能优化的始作俑者 他们也有很多的共性 我们先来回顾一下class组件性能优化的点 调用 setState 就会触发组件的重新渲染 无论前后 state 是否相
  • 64位系统树莓派部署yolo-fatestv2---超多坑

    最近在研究yolo fastest 开始面对作者大大的一堆部署的指令在pycharm的终端里面一顿操作 然后一路报错 后来才发现原来都是linux的指令 后来在虚拟机上也尝试部署过 成功之后本来想直接挪到树莓派上 但是尝试许久都以失败告终
  • mysql修改权限

    mysql权限 显示用户权限 mysql gt show grants for jeffrey localhost 一般 数据库管理员首先建立用户 定义其非特权特征 例如其密码 是否使用安全链接以及对服务器资源的访问限制 而后使用grant
  • java枚举类的定义和使用

    开始时间 2018年8月11日11 04 35 结束时间 2018年8月11日12 30 37 累计 1小时 枚举类的对象是有限个 对象个数 一个可以看做单例模式的实现 多个 为枚举类 1 如何定义 cccccccc 1 私有化类的构造器
  • 服务器虚拟化解决方案

    根据以往经验推断 一台主流双路 PC 服务器可以承担 3 6 个应用系统在其 上运行 本期项目总共有 N 个业务系统 考虑到硬件资源需具备一定的冗余能 力和实现高可用 HA 在线迁移 动态调度 后期扩展等诸多因素 推荐 2 台双 路 PC
  • 智能指针 -- unique_ptr

    源码分析 源码链接 gcc unique ptr h at master gcc mirror gcc GitHub 上面链接中的源码是unique ptr的完整定义 我们来简化其类结构看看 template