【问题标题】:Confusing operation in c++ program while understanding move semantics在理解移动语义的同时在 C++ 程序中混淆操作
【发布时间】:2018-06-05 00:22:56
【问题描述】:

我试图在 C++ 中掌握移动语义、右值、左值的概念,但我正面临一个问题。我首先看的是这个流行的答案 - https://stackoverflow.com/a/3109981/9576161

我根据该回复编写了一个小程序,以了解发生了什么。我正在使用 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 行(其中显示“构造函数2 被调用”)。它有什么作用? datathat.data 不是两个字符指针吗?为什么data 的价值没有变化? data 现在不应该等于that.data 的值,即0x7fffac01bb80 吗?相反,似乎某种memcopy 正在发生,that.data 指向的字符串现在由data 指向。任何有关正在发生的事情的提示都会有所帮助。

【问题讨论】:

  • data 当然最好改变值。它只是窃取了thatdata 并将其清空以防止稍后发生意外。
  • 您不需要编写整个类来测试两个指针在相互分配时的作用。
  • using namespace std; 也被使用时,很高兴看到string 作为类名。好主意!
  • @user4581301 我不明白。 data 是一个字符指针,不是吗?我没有正确打印指针的值吗?我认为这就是问题所在。而不是&amp;data,我认为(void *)datacout 实际指针值。对吗?
  • @slava 我正在使用::。很抱歉造成混乱。

标签: c++ c++11 move-semantics rvalue-reference


【解决方案1】:

&amp;data 的类型是char**。也就是存储了一些char的内存位置的指针的内存位置。

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

如果不是打印data 的地址,而是print the address stored in data,您可以看到您在移动构造函数中窃取了that 拥有的chars 数组。

【讨论】:

    猜你喜欢
    • 2011-06-26
    • 2010-11-24
    • 2014-06-25
    • 2013-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多