Несмотря на передачу rvalue, почему не вызывается мой конструктор перемещения? - PullRequest
3 голосов
/ 15 мая 2019

Я создаю строку класса путем определения конструктора по умолчанию, копирования и перемещения.Я пытаюсь создать объекты, ожидая вызова каждого конструктора.Как и ожидалось, вызывается конструктор default и copy, но когда я передаю rvalue (временный объект), я все еще вижу, что конструктор move НЕ вызывается.

#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 : Я передаю временный объект.Итак, я ожидаю, что будет вызван конструктор перемещения , но вызывается конструктор по умолчанию .

Я не могу понять, что мне не хватает.Пожалуйста, помогите, спасибо.

Ответы [ 2 ]

3 голосов
/ 15 мая 2019

Вы определили data как char *.

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

означает, что «копия» data в конструкторе перемещения не является полной копией.

Редактировать: Теперь это было бы нормально, поскольку вы можете "потрошить" значение r, однако, когда оно разрушает, вы делаете это, используя nullptr:

Когда вы звоните

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

в деструкторе данные равны нулю, у вас неопределенное поведение. Все может случиться.

1 голос
/ 15 мая 2019

Действительно, он ведет себя так, как вы говорите с GCC и Clang, но конструктор перемещения вызывается с VC ++. Выглядит как ошибка, тогда вы должны двигаться явно с помощью std :: move ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...