c++ - 来自 "The C++ Programming Language 4th Edition"第 19.3.3.1 节的代码是否有效?

标签 c++

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

类接口(interface)如下所示:

#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 具有用户定义的构造函数、复制操作、移动操作和析构函数)。

最佳答案

How can String::copy_from() use memcpy() to copy the class?

intchar 和匿名 union 都可以轻松复制。因此,虽然您无法执行 Stringmemcpy,但您可以执行其成员memcpy。所有的人,同时。技术上正确的代码是:

memcpy(&this->sz, &x.sz, sizeof(x));

即为这个对象的成员复制存储的内存范围。这是由标准布局类型的规则保证的。对于标准布局类型,成员按定义顺序存储。因此,如果您从第一个开始,并覆盖所有对象的范围,那么应该复制成员。

但是,标准还规定标准布局类型的第一个成员子对象必须与对象本身具有相同的地址:

If a standard-layout class object has any non-static data members, its address is the same as the address of its first non-static data member.

这意味着 &this->sz 必须是 this 相同的地址,并且 &x.sz 必须与 &x 相同的地址。

所以去掉中间人:

memcpy(this, &x, sizeof(x));

这只是因为标准布局类型的规则才被允许。


一个更大的问题是 copy_from 从不检查self 赋值。 memcpy 不适用于重叠的内存范围。也许 operator= 和类似的函数已经检查过了。

关于c++ - 来自 "The C++ Programming Language 4th Edition"第 19.3.3.1 节的代码是否有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51386532/

相关文章:

c++ - 在具有父 ID 的一般树中找到最低公共(public)祖先

C++从字符串中删除标点符号

c++ - C2143 : syntax error: missing ';' before '*' & C4430: missing type specifier - int assumed. 注意:C++ 不支持default-int

c++ - 在 C/C++ 中用两个线程操作不同的数组索引时,是否需要同步?

c++ - Vector.end() 在 C++ 中删除元素后的意外行为

c++ - 我可以一次性检查一小组 boolean 值吗?

c++ - 优化标志删除对外部变量的 undefined reference

c++ - 共享内存中的 SRW 锁

c++ - 执行某些代码后可以显式调用构造函数吗?

C++:如何将文件作为参数传递?