在构造函数中浅复制一个字符串数组

时间:2018-08-18 01:48:57

标签: c++

我的头文件中有一个字符串数组(string references[10]),作为类的私有变量。

如果在该类tome(string *initialList)中有构造函数,该如何浅表复制?

我要设置references = initialList;

最好的方法是什么?

头文件:

#ifndef TOME_H
#define TOME_H
#include <string>

using namespace std;

class tome;

ostream &operator << (ostream &, const tome &);

class tome
{
public:
    tome(string , int, string);
    tome(string, int, string , string*);
    ~tome();
    int getTomeSize();
    string getSpell(int) const;
    string* getReferences();
    string getName();
    string getAuthor();
    tome operator+(string* add);
    friend ostream &operator << (ostream &output, const tome &t);
    void operator=(const tome &oldTome);
private:
    string references[10];
    string tomeName;
    string author;
    int spellsStored;

    friend ostream &operator << (ostream &, const tome &);
};
#endif

tome.cpp构造函数:

tome::tome(string name, int tomeSize, string authorName, string* initialList)
{
tomeName = name;
author = authorName;
spellsStored = tomeSize;
}

1 个答案:

答案 0 :(得分:1)

原始数组或std::array形式的数组,总是包含数据(如果是指针数组,则“ data”是指针!),因此如果您有std::string数组,则不能进行浅拷贝,因为std :: string不提供浅拷贝。

对于浅拷贝,您需要引用或指针(不考虑可见性,请根据需要进行调整):

class A
{
    std::array<std::string, 10> data; // using std::array for its superior interface...
};
class B
{
    std::array<std::string, 10>* data; // references an array of some A
}

很显然,您现在需要某种形式的生命周期管理,以确保只要引用A仍然有效,或者至少只要{ {1}}仍使用此引用。如果您做的不正确,您将最终陷入不确定的行为或内存泄漏...

如果使用智能指针,则可以免费获得此内存管理:

B

现在,不同的B(您可以任意数量)可以共享任意数据,一旦所有引用该数据的class C { std::shared_ptr<std::array<std::string, 10>> data; }; 被销毁(但不会更早),则将其删除,并且您可以安全地避免两者以上问题。现在,只需将智能指针分配给另一个指针即可完成浅拷贝:

C

但是,对C中一个数据的更改对于共享同一数组的所有其他C::C(std::shared_ptr<std::array<std::string, 10>>& data) : data(data) { } // ^^^^^^^^^^ // std::shared_ptr's constructor does the necessary stuff... 来说都是可见的。在某些情况下可能会需要 ,如果您不谨慎处理此问题,可能会给其他情况带来很大的惊喜。

为了避免麻烦,您可能更希望使用深层副本。我建议使用C,因为它具有与C相似的高级接口,因此您可以轻松地正确分配;让我们适当地扩展到类std::array之上:

std::vector

如果您坚持要使用原始数组:

A

假设我们总是有长度为10的数组-如果某个时候某处违反了此条件,则可能会遇到很大的麻烦。更好的方法是将大小与数组一起传递并进行适当的检查。您看到,A::A(std::array<std::string, 10>& data) : data(data) { } // ^^^^^^^^^^ // simply assign, std::array's constructor does the rest... 避免了所有这些麻烦,并且避免了原始数组和传递长度之间的不匹配(另一方面,您不能以这种方式传递子数组;不过,您可以提供带有两个附加参数的重载class D { std::string[10] data; D(std::string* data) { std::copy(data, data + 10, this->data); } }; 下面的方法允许选择子范围。如果您希望能够传递任意长度的数组:

std::array

最后:适当的typedef可以使您一方面安全地进行很多键入操作,但更重要的是,可以防止出现错误(也请使用常量):

size_t offset, size_t length