第19.3节在一章中介绍了字符串表示形式,该章的重点是运算符重载,特别是特殊运算符[]
,->
和()
。它实现copy_from()
作为辅助功能,如下所示:
void String::copy_from(const String &x)
// make *this a copy of x
{
if (x.sz <= short_max)
{
memcpy(this, &x, sizeof(x);
ptr = ch;
}
else
{
ptr = expand(x.ptr, x.sz+1);
sz = x.sz;
space = 0;
}
}
类接口如下:
#ifndef STRING_EXERCISE_H
#define STRING_EXERCISE_H
namespace simple_string
{
class String;
char *expand(const char *ptr, int n);
}
class String
{
public:
String(); // default constructor x{""}
explicit String(const char *p); // constructor from C-style string
String(const String &s); // copy constructor
String &operator=(const String& s); // copy assignment
String(String &&s) // move constructor
String &operator=(String &&s) // move assignement
~String() // destructor
char &operator[](int n); // unchecked element access
char operator[](int n) const;
char &at(int n); // checked element access
char at(int n) const;
String &operator+=(char c) // add char c to the end
const char *c_str(); // c-style string access
const char *c_str() const;
int size() const; // number of elements
int capacity() const; // elements plus available space
private:
static const short short_max = 15;
int sz;
char *ptr;
union
{
int space; // unused allocated space
char ch[short_max+1]; // leave space for terminating 0
};
void check(int n) const; // range check
void copy_from(const String &x);
void move_from(String &x);
}
#endif
String::copy_from()
如何使用memcpy()
复制课程?我认为复制的类必须是可复制的(它不是,因为String
具有用户定义的构造函数,复制操作,移动操作和析构函数)。
答案 0 :(得分:5)
String::copy_from()
如何使用memcpy()
复制课程?
int
,char
和匿名联合都可以轻松复制。因此,尽管您无法执行memcpy
中的String
,但是可以执行其成员中的memcpy
。所有这些,一次全部。技术上正确的代码是:
memcpy(&this->sz, &x.sz, sizeof(x));
复制该对象成员的存储空间范围,这是由标准布局类型的规则保证的。对于标准布局类型,成员按定义顺序存储。因此,如果您从第一个开始,并涵盖所有对象的范围,那应该复制成员。
但是,该标准还规定,标准布局类型的第一个成员子对象必须具有与对象本身相同的地址:
如果标准布局类对象具有任何非静态数据成员,则其地址与其第一个非静态数据成员的地址相同。
这意味着&this->sz
必须与this
相同的地址,并且&x.sz
必须与&x
相同的地址。
所以就切掉中间人:
memcpy(this, &x, sizeof(x));
仅由于标准布局类型的规则,才允许这样做。
一个更大的问题是copy_from从不检查 self 分配。 memcpy
不适用于重叠的内存范围。也许operator=
和类似函数已经对此进行了检查。
答案 1 :(得分:-1)
我认为您缺少的是代码正在显示一种称为短字符串优化的东西,该字符串允许将字符串存储在对象的某些缓冲存储器中。
是的,对于短字符串,整个类都可以被复制,因为这就是对象标识的全部内容。 我不会那样做,但是概念是对于短字符串,您可以逐个元素地复制类的内容。 (并重新分配ptr
)。
我会这样做,避免讨论,而且我认为效率不低。
if (x.sz <= short_max)
{
sz = x.sz;
ptr = ch;
memcpy(&ch, &x.ch, sizeof(ch));
}