简体   繁体   English

复制构造函数const char *和Shared_ptr

[英]Copy Constructor const char* and Shared_ptr

I have a class Keywords : 我有一堂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;
}

And I want to construct a copy Constructor for const char* and vector<shared_ptr<RegularExpression>> 我想为const char*vector<shared_ptr<RegularExpression>>构造一个副本构造器。

Am I coding it correctly? 我编码正确吗?

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]));
}

From What i understand I make a copy The Const char* and the vector of shared_ptr. 根据我的理解,我制作了一份Const char *和shared_ptr的向量。

Thank you. 谢谢。

* So After the removal of const char * i'll have* * 因此,在删除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;
}

and the copy constructor would be: 复制构造函数为:

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]));
}

Destcrutor: 委托人:

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

You have two options here. 您在这里有两个选择。 The one you probably want to use is the compiler-provided default copy constructor: 您可能要使用的是编译器提供的默认副本构造函数:

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

In this context, the default copy constructor will do exactly what you (most likely) want: it will make a copy of the vreg vector, which means copying the shared_ptr elements of the vector — but not deep-copying the RegularExpression objects themselves! 在这种情况下,默认的复制构造函数将执行您(最可能)想要的操作:它将复制vreg向量,这意味着复制该向量的shared_ptr元素-而不是深度复制RegularExpression对象本身! You (most likely) don't want to deep-copy those objects, because they're expensive to copy, and I would guess that it's just as appropriate to use the originals as to use copies. 您(最有可能)不想深度复制那些对象,因为它们的复制成本很高,而且我猜想使用原稿和使用副本一样合适。 Normally you'd have to worry about memory management — whose job is it to free the originals now that two different Keywords objects claim to own them? 通常,您必须担心内存管理-既然两个不同的Keywords对象声称拥有它们,那么释放原件的工作是谁? — but in this case that's 100% solved, because the two Keywords objects will share ownership. —但是在这种情况下,这是100%解决的,因为两个Keywords对象将共享所有权。 That's what shared_ptr does . 这就是shared_ptr 所做的

This is a great example of what's known as The Rule of Zero . 这是所谓的零规则的一个很好的例子。 The familiar Rule of Three (or Five, or maybe Six) says that if you define one special member function, you should define them all. 熟悉的3(或5,或6)规则说,如果定义一个特殊的成员函数,则应全部定义它们。 The Rule of Zero says that you shouldn't define any special member functions unless you're doing something really tricksy. 零规则说,除非您做的确实很棘手,否则您不应定义任何特殊的成员函数


If you want to be tricksy here, and write a custom copy-constructor that does do deep copies of the RegularExpression elements, 如果你成为这里调皮,并编写自定义的拷贝构造函数, 确实做的深层副本RegularExpression元素,

...well, you should ask yourself why you're not just using std::vector<RegularExpression> vreg in the first place — then you could still use the Rule of Zero, because the default copy-constructor would make deep copies for you just as you apparently want. ...好吧,你应该问自己为什么为什么不首先使用std::vector<RegularExpression> vreg仍然可以使用零规则,因为默认的复制构造函数会为就像您显然想要的那样。

But if you are unshakeable in your desire to do tricksy things, you'd do it like this: 但是,如果您对做棘手的事情不愿动摇 ,可以这样做:

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

This implementation might still not do what you want; 此实现可能仍然无法满足您的要求; for example, if before the copy operation we have rhs.vreg[0] == rhs.vreg[1] , our constructor will quietly make two copies of that single RegularExpression object, and give us a new Keywords object *this such that this->vreg[0] != this->vreg[1] . 例如,如果复制操作之前,我们已经rhs.vreg[0] == rhs.vreg[1]我们的构造会悄悄地作出这样的单一的两个副本RegularExpression对象,并给我们一个新的Keywords对象*this使得this->vreg[0] != this->vreg[1] This is merely a specific application of the general principle that it's hard to make a copy of an arbitrary pointer graph. 这只是一般原理的特定应用,因为很难复制任意指针图。

Did you notice how long this line of code is? 您注意到这行代码多长时间了吗?

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

That's a red flag in normal C++11 code. 在正常的C ++ 11代码中,这是一个危险信号。 In normal code, we don't have to write explicit types like RegularExpression ; 在普通代码中,我们不必编写像RegularExpression这样的显式类型; the compiler can just infer the types. 编译器可以推断类型。 If I wanted to copy sptr , I could just write vreg.emplace_back(sptr) — no explicit types! 如果我想复制sptr ,我可以只写vreg.emplace_back(sptr) -没有显式类型! But here I had to write out std::make_shared<RegularExpression>(...) . 但是在这里我不得不写出std::make_shared<RegularExpression>(...) This is awkward... because I'm Doing It Wrong . 这很尴尬... 因为我做错了 It's not normal to take a shared_ptr , dereference it, copy-construct the thing pointed to by the shared_ptr , and then re-wrap that in a new shared_ptr with different ownership. 这是不正常采取shared_ptr ,取消对它的引用,复制,构建东西指向shared_ptr ,然后重新包装,在一个新shared_ptr不同的所有权。 That's a complicated and bizarre operation, and so it kind of makes sense that the syntax to do it in C++11 is complicated and bizarre. 这是一个复杂而奇怪的操作,因此在C ++ 11中执行该操作的语法是复杂而奇怪的,这在一定程度上是有意义的。

I recommend not being tricksy, in this instance. 在这种情况下,我建议不要太棘手。 :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM