为什么当我 return 一个堆分配对象而不是堆栈分配对象时调用复制构造函数?
Why is copy constructor being invoked when I return a heap allocated object but not for stack allocated object?
我有一个 state
class 有一步棋 assignment/constructor。副本assingment/constructor设置为delete
.
我很困惑为什么在下面的函数中(returns 一个 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&)’
现代编译器足够聪明,可以执行 RVO (What are copy elision and return value optimization?)
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;
}
这就是为什么我们在这里 return 实际上是创建的对象(编译器可以直接为函数的 return 值创建它,以避免复制)。
但在第二种变体中,您试图从 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;
}
您还通过丢弃指向堆的指针来泄漏内存,您已经在其中创建了一个对象。
我有一个 state
class 有一步棋 assignment/constructor。副本assingment/constructor设置为delete
.
我很困惑为什么在下面的函数中(returns 一个 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&)’
现代编译器足够聪明,可以执行 RVO (What are copy elision and return value optimization?)
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;
}
这就是为什么我们在这里 return 实际上是创建的对象(编译器可以直接为函数的 return 值创建它,以避免复制)。
但在第二种变体中,您试图从 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;
}
您还通过丢弃指向堆的指针来泄漏内存,您已经在其中创建了一个对象。