在理解移动语义的同时混淆c++程序中的操作

Confusing operation in c++ program while understanding move semantics

我试图掌握 c++ 中移动语义、右值、左值的概念,但遇到了一个问题。我首先查看这个流行的答案 -

我根据那个回复写了一个小程序来了解是怎么回事。我正在使用 g++(在 linux 上)和 -fno-elide-constructors 进行编译,编译器不进行右值优化。

这里是小程序:

#include <iostream>                                                                                                                                                      
#include <cstring>                                                                                                                                                       

using namespace std;                                                                                                                                                     

class string  {                                                                                                                                                          

    public:                                                                                                                                                              
        char* data;                                                                                                                                                      
        string (const char* p) {                                                                                                                                         
            cout << "Constructor 1 called\n";                                                                                                                            
            size_t size = strlen(p) + 1;                                                                                                                                 
            data = new char[size];                                                                                                                                       
            cout << "this location is: " << this << endl;
            memcpy (data,p,size);
        }

        string (string&& that) {
            cout << "Constructor 2 called\n";
            //cout << "data is " << data << " data location is: " << &data << endl;
            cout << "data location is: " << &data << endl;
            cout << "that.data is " << that.data << " that.data location is: " << &that.data << endl;
            data = that.data;
            that.data = nullptr;
            cout << "this location is: " << this << " data is: " << data << endl;
            cout << "data location is: " << &data << endl;
            cout <<  "that.data location is: " << &that.data << endl;
        }

        ~string() {
            delete[] data;
            cout << "Destructor called for object located at: " << this << endl;
        }

        void print() {
            cout << "String is: " << data << endl;
        }
};

int main () {
    ::string R = "12345";
    cout << "R constructed and located at: " << &R << endl << endl;
    return 0;
}

在 运行 程序上,我看到以下结果:

ubuntu@thinkpad:~/programming_practice/c_projects$ g++ -fno-elide-constructors move_semantics_short.cpp 
ubuntu@thinkpad:~/programming_practice/c_projects$ ./a.out 
Constructor 1 called
this location is: 0x7fffac01bb80
Constructor 2 called
data location is: 0x7fffac01bb78
that.data is 12345 that.data location is: 0x7fffac01bb80
this location is: 0x7fffac01bb78 data is: 12345
data location is: 0x7fffac01bb78
that.data location is: 0x7fffac01bb80
Destructor called for object located at: 0x7fffac01bb80
R constructed and located at: 0x7fffac01bb78

Destructor called for object located at: 0x7fffac01bb78
ubuntu@thinkpad:~/programming_practice/c_projects$ 

注意第二个构造函数中的 data = that.data 行(它表示 "Constructor 2 is called")。它有什么作用? datathat.data 不都是字符指针吗?为什么 data 的值没有变化? data 现在不应该等于 that.data 的值 0x7fffac01bb80 吗?相反,似乎发生了某种 memcopythat.data 指向的字符串现在由 data 指向。任何有关正在发生的事情的提示都会有所帮助。

&data的类型是char**。也就是存放一些char.

的内存位置的指针的内存位置

data = that.data; 不会使 &data 等于 &that.data。它只是让 datathat.data 相等。它们现在指向同一个 char,但它们各自独立存在于内存中。

如果您 print the address stored in data 没有打印 data 的地址,您可以看到您正在窃取 that 拥有的 char 数组在你的移动构造函数中。