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

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

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

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 ответ

Решение

Современные компиляторы достаточно умны, чтобы выполнять 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;
}

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

Другие вопросы по тегам