广义副本构造函数

时间:2017-05-28 12:05:14

标签: c++ templates inheritance polymorphism

为什么像shared_ptr这样的类在其构造函数中有另一个模板?

例如:

template<class T> class shared_ptr {
public:
  template<class Y>
  explicit shared_ptr(Y * p);

我一直在阅读Scott Meyers的 Effective C ++ ,第45项,其中说它背后的想法是通过它们实现多态性;也就是说,如果B来自A,则从shared_ptr<A>构造shared_ptr<B>

但是没有定义像

这样的构造函数
explicit shared_ptr(T * p);

足够?我的意思是,这段代码运行得很好:

class C1 {
};

class C2 : public C1 {
};

template<typename T>
class A
{
public:
  A(T &a)
  {
    var1 = a;
  }

  T var1;
};

int main(int argc, char *argv[])
{
  C2 c2;
  A<C1> inst1(c2);
}

那么为什么我们需要另一个构造函数模板呢?

2 个答案:

答案 0 :(得分:13)

如果没有模板构造函数,以下代码将具有未定义的行为:

#include <memory>

class Base {};
class Derived : public Base {};

int main() {
    std::shared_ptr<Base> ptr( new Derived );
}

如果shared_ptr只占用Base*,则会强制最终在delete指针上调用Base*。但由于Base没有虚拟析构函数且指针实际指向Derived,因此这是未定义的行为。

但实际上,上面的代码是格式良好的。 shared_ptr的模板构造函数使用Derived*指针并存储在原始delete指针上调用Derived*的自定义删除器,这很好。

答案 1 :(得分:0)

explicit shared_ptr(T * p);

如果shared_ptr只有这个构造函数,它就会破坏它的整个目的,即提供一个引用计数指针。

引用计数(或者更确切地说是指针)是shared_ptr的一部分。每次创建,销毁或复制shared_ptr时都应更新它。如果将shared_ptr传递给复制例程,则只能实现最后一部分。传递裸指针将创建引用计数为1的shared_ptr

引用计数指针仅在其引用计数超过1时共享。对于您的方案,不清楚这是如何发生的。

一些引用计数功能由普通(非模板)复制构造函数提供。但不是全部。

例如,

 std::shared_ptr<Derived> d;
 std_shared_ptr<Base> b;
 ...
 b = d;
如果没有模板“copy”构造函数,

将无法编译。我们希望共享poiters提供与普通指针相同的多态行为,因此我们希望上述构造为Just Work。模板构造函数提供了。