繁体   English   中英

尽管传递了一个右值,为什么我的移动构造函数不会被调用?

[英]Despite passing an rvalue, why isn't my move constructor getting called?

我通过定义默认,复制和移动构造函数来创建一个类字符串。 我尝试创建期望每个构造函数被调用的对象。 正如所料,默认&复制构造函数被调用,但是当我传递一个rvalue(临时对象)时,我仍然看到移动构造函数未被调用。

#include <iostream>
#include <cstdlib>
#include <cstring>

class string
{
    char * data;
public:
    string(const char * p = nullptr)
    {
        if(p == nullptr) return;
        std::cout << "string(const char * p)" << std::endl;
        size_t size = strlen(p) + 1;
        data = new char[size];
        memcpy(data, p, size);
    }
    ~string()
    {
        std::cout << "~string() - " << data << std::endl;
        delete[] data;
    }
    string(const string & that)
    {
        std::cout << "string(const string &)" << std::endl;
        size_t size = strlen(that.data) + 1;
        data = new char[size];
        memcpy(data, that.data, size);
    }
    string(string && that)
    {
        std::cout << "string(string && )" << std::endl;
        data = that.data;
        that.data = nullptr;
    }
    void showData() { std::cout << data << std::endl; }
    string operator+(const string & other)
    {
        size_t datasize = strlen(data);
        size_t othersize = strlen(other.data);
        size_t totalsize = datasize + othersize + 1;
        char * sData = new char[totalsize];
        memcpy(sData, data, strlen(data));
        memcpy(sData+datasize, other.data, totalsize-datasize);
        string s(sData);
        delete[] sData;
        return s;

    }
    string & operator=(string that)
    {
        char * tmp = data;
        data = that.data;
        that.data = tmp;
        return *this;
    }
};

int main()
{
    string s1{"stackoverflow"};  // s1
    string s2{s1};               // s2
    string s3{string("stack")+string("exchange")};  // s3
}

s1 :正在按预期调用默认构造函数

s2 :调用复制构造函数 ,也如预期的那样。

s3 :我正在传递一个临时物体。 所以,我希望调用move构造函数 ,但调用默认构造函数

我无法理解我所缺少的东西。 请帮助,谢谢。

您已将data定义为char *

string(string && that)
{
    std::cout << "string(string && )" << std::endl;
    data = that.data;
    that.data = nullptr;
}

表示移动构造函数中的data “副本”不是深层副本。

编辑:现在,这没关系,因为你可以“消除”右边界,但是,当它破坏你使用nullptr这样做时:

你打电话的时候

std::cout << "~string() - " << data << std::endl;

在析构函数中,data为null,您有未定义的行为。 什么事情都可能发生。

实际上它的行为和GCC和Clang一样,但是用VC ++调用移动构造函数。 看起来像一个bug,然后你应该用std :: move()显式移动。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM