我的头文件中有一个字符串数组(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;
}
答案 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