【问题标题】:Copy Constructor const char* and Shared_ptr复制构造函数 const char* 和 Shared_ptr
【发布时间】:2013-07-30 11:26:10
【问题描述】:

我有一堂课Keywords:

#include <boost/lambda/lambda.hpp>
class Keywords
{
    public:
        ///Constructor
        Keywords(const char*,vector<shared_ptr<RegularExpression>>,vector<string>);
        Keywords(const Keywords& other);
    private:
        const char * xmlFile;
        vector<shared_ptr<RegularExpression>> vreg;
        vector<string> sw;
}

我想为const char*vector&lt;shared_ptr&lt;RegularExpression&gt;&gt;构造一个拷贝构造函数

我的编码是否正确?

Keywords::Keywords(const Keywords& other):xmlFile(new char[100]),vreg(other.vreg.size())
{
    strcpy((char*)xmlFile, (char*)other.xmlFile);
    for (std::size_t i = 0; i < other.vreg.size(); ++i)
        vreg[i] = shared_ptr<RegularExpression>(new RegularExpression(*other.vreg[i]));
}

据我了解,我复制了 Const char* 和 shared_ptr 的向量。

谢谢。

*所以在去掉 const char * 后我就有了*

class Keywords
{
    public:
        ///Constructor
        Keywords(string,vector<shared_ptr<RegularExpression>>,vector<string>);
        Keywords(const Keywords& other);
    private:
        string xmlFile;
        vector<shared_ptr<RegularExpression>> vreg;
        vector<string> sw;
}

复制构造函数是:

Keywords::Keywords(const Keywords& other):vreg(other.vreg.size()),sw(other.sw)
{
    for (std::size_t i = 0; i < other.vreg.size(); ++i)
        vreg[i] = shared_ptr<RegularExpression>(new RegularExpression(*other.vreg[i]));
}

解说员:

Keywords::~Keywords()
{
    sw.clear();
    vreg.erase(vreg.begin());
}

【问题讨论】:

  • 为什么不用std::string 而不是char*?编译器生成的副本成员是正确的。
  • 是的,我正在考虑。是的,这是真的。而不是这个
  • 还有char const *std::string的隐式转换,所以你可以用同样的方式调用你的构造函数
  • 智能指针矢量做得好!
  • 使用shared_ptr 将允许多个对象共享同一个RegularExpression 的所有权,但您不会共享所有权,因为您的复制构造函数为新的RegularExpression 对象创建了新的RegularExpression 对象。如果这是你想要的,那你就写对了。

标签: c++ constructor shared-ptr


【解决方案1】:

这里有两个选择。您可能想要使用的是编译器提供的默认复制构造函数:

class Keywords {
    std::string xmlFile;
    std::vector<std::shared_ptr<RegularExpression>> vreg;
    std::vector<std::string> sw;

public:
    Keywords(const char *xmlFile,
             const std::vector<std::shared_ptr<RegularExpression>>& vreg,
             const std::vector<std::string>& sw)
      : xmlFile(xmlFile), vreg(vreg), sw(sw) {}

    // Look, Ma, no special member functions!
};

在这种情况下,默认的复制构造函数将完全按照您(很可能)想要的方式执行:它将复制vreg 向量,这意味着复制向量的 shared_ptr 元素— 但不是深度复制 RegularExpression 对象本身!您(很可能)不想深度复制这些对象,因为它们的复制成本很高,而且我猜想使用原件和使用副本一样合适。通常你不得不担心内存管理——既然两个不同的Keywords 对象声称拥有它们,那么释放原件是谁的工作? — 但在这种情况下,这 100% 已解决,因为两个 Keywords 对象将共享所有权。这就是shared_ptr 所做的

这是所谓的零规则的一个很好的例子。熟悉的三规则(或五,或者可能是六)说,如果你定义一个特殊的成员函数,你应该定义它们。零规则说你不应该定义任何特殊的成员函数,除非你在做一些非常棘手的事情。


如果您想要在这里耍花招,并编写一个自定义的复制构造函数,确实RegularExpression元素进行深层复制,

...嗯,你应该问自己为什么你不只是首先使用std::vector&lt;RegularExpression&gt; vreg - 然后你仍然可以使用零规则,因为默认的复制构造函数会为你制作深拷贝如你所愿。

但如果你不可动摇想要做一些棘手的事情,你会这样做:

class Keywords {
    std::string xmlFile;
    std::vector<std::shared_ptr<RegularExpression>> vreg;
    std::vector<std::string> sw;

public:
    Keywords(const char *xmlFile,
             const std::vector<std::shared_ptr<RegularExpression>>& vreg,
             const std::vector<std::string>& sw)
      : xmlFile(xmlFile), vreg(vreg), sw(sw) {}

    Keywords(const Keywords& rhs)
      : xmlFile(rhs.xmlFile), sw(rhs.sw)
    {
        vreg.reserve(rhs.vreg.size());
        for (auto&& sptr : rhs.vreg) {
            vreg.emplace_back(std::make_shared<RegularExpression>(*sptr));
        }
    }

    // Don't forget to implement copy-assignment too!
    // I'm just going to delete it here to keep anyone from using it.
    //
    Keywords& operator= (const Keywords&) = delete;
};

这个实现可能仍然不能做你想做的事;例如,如果在复制操作之前我们有rhs.vreg[0] == rhs.vreg[1],我们的构造函数将悄悄地复制那个单一的RegularExpression 对象,并给我们一个新的Keywords 对象*this,这样this-&gt;vreg[0] != this-&gt;vreg[1]。这只是对难以复制任意指针图的一般原则的具体应用。

你注意到这行代码有多长了吗?

    vreg.emplace_back(std::make_shared<RegularExpression>(*sptr));

这是普通 C++11 代码中的一个危险信号。在普通代码中,我们不必编写像RegularExpression 这样的显式类型;编译器只能推断类型。如果我想复制sptr,我可以写vreg.emplace_back(sptr)——没有明确的类型!但在这里我不得不写出std::make_shared&lt;RegularExpression&gt;(...)。这很尴尬...因为我做错了获取shared_ptr 是不正常的,取消引用它,复制-构造shared_ptr 所指向的东西,然后将其重新包装在具有不同所有权的新shared_ptr 中。这是一个复杂而奇怪的操作,因此在 C++11 中执行此操作的语法复杂而奇怪是有道理的。

在这种情况下,我建议不要耍花招。 :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-18
    • 2021-08-28
    • 2010-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多