Почему конструктор копирования вызывается, когда я возвращаю выделенный объект кучи, но не для выделенного объекта стека? - PullRequest
0 голосов
/ 07 ноября 2018

У меня есть класс state, который имеет назначение / конструктор перемещения. Копирование / конструктор установлены на delete.

Я запутался, почему в следующей функции (которая возвращает state объект) компилируется и работает так:

state propagator::PROPAGATE(date & TargetDate)
{
    jmethodID jmid_PROPAGATE = ENV->GetMethodID(this->jcls_PROPAGATOR, "propagate", "(path/to/date;)path/to/state;");
    jobject jobj_PROPAGATED_STATE = ENV->CallObjectMethod(this->jobj_PROPAGATOR, jmid_PROPAGATE, TargetDate.get_DATE_JOBJECT());

    state PROPAGATED_STATE(this->ENV);
    PROPAGATED_STATE.set_STATE_JOBJECT(jobj_PROPAGATED_STATE);
    return PROPAGATED_STATE;

    //state * PROPAGATED_STATE = new state(ENV);
    //PROPAGATED_STATE->set_STATE_JOBJECT(jobj_PROPAGATED_STATE);
    //return *PROPAGATED_STATE;
}

но жалуется, что конструктор копирования был удален, когда я пытаюсь это сделать:

state propagator::PROPAGATE(date & TargetDate)
{
    jmethodID jmid_PROPAGATE = ENV->GetMethodID(this->jcls_PROPAGATOR, "propagate", "(path/to/date;)path/to/state;");
    jobject jobj_PROPAGATED_STATE = ENV->CallObjectMethod(this->jobj_PROPAGATOR, jmid_PROPAGATE, TargetDate.get_DATE_JOBJECT());

    //state PROPAGATED_STATE(this->ENV);
    //PROPAGATED_STATE.set_STATE_JOBJECT(jobj_PROPAGATED_STATE);
    //return PROPAGATED_STATE;

    state * PROPAGATED_STATE = new state(ENV);
    PROPAGATED_STATE->set_STATE_JOBJECT(jobj_PROPAGATED_STATE);
    return *PROPAGATED_STATE;
}

Выход компилятора:

error: use of deleted function ‘state::state(const state&)’

1 Ответ

0 голосов
/ 07 ноября 2018

Современные компиляторы достаточно умны, чтобы выполнять RVO ( Что такое оптимизация копирования и возврата значений? )

state propagator::PROPAGATE(date & TargetDate)
{
    jmethodID jmid_PROPAGATE = ENV->GetMethodID(this->jcls_PROPAGATOR, "propagate", "(path/to/date;)path/to/state;");
    jobject jobj_PROPAGATED_STATE = ENV->CallObjectMethod(this->jobj_PROPAGATOR, jmid_PROPAGATE, TargetDate.get_DATE_JOBJECT());

    state PROPAGATED_STATE(this->ENV);
    PROPAGATED_STATE.set_STATE_JOBJECT(jobj_PROPAGATED_STATE);
    return PROPAGATED_STATE;
}

Именно поэтому здесь мы возвращаем фактически созданный объект (компилятор может просто создать его на месте для возвращаемого значения функции, чтобы избежать копирования).

Но во втором варианте вы пытаетесь создать объект в стеке из объекта в HEAP, и здесь нельзя использовать RVO или перемещение. Вот почему он пытается выполнить удаленную копию.

state propagator::PROPAGATE(date & TargetDate)
{
    jmethodID jmid_PROPAGATE = ENV->GetMethodID(this->jcls_PROPAGATOR, "propagate", "(path/to/date;)path/to/state;");
    jobject jobj_PROPAGATED_STATE = ENV->CallObjectMethod(this->jobj_PROPAGATOR, jmid_PROPAGATE, TargetDate.get_DATE_JOBJECT());

    state * PROPAGATED_STATE = new state(ENV);
    PROPAGATED_STATE->set_STATE_JOBJECT(jobj_PROPAGATED_STATE);
    return *PROPAGATED_STATE;
}

Также вы теряете память, отбрасывая указатель на кучу, где вы создали объект.

...