【发布时间】:2020-05-20 09:19:30
【问题描述】:
我正在适应带有参数const vector<pair<int32_t, A>>& as 的接口。
为了避免多重构造和多重破坏,我写CreateAs如下。
我原以为它会触发 create move del 一次,但结果却触发了两次 move 和 del。
- 是什么原因?
- 我这样做是为了让
A对象可以自动销毁自己,即使有new但没有delete。我做得对吗?
复制它:https://repl.it/@unix1/ShrillFirsthandAdvance
#include <iostream>
#include <vector>
using namespace std;
struct A {
A() { cout << "A()" << endl; }
A(int32_t a) : a_(a) { cout << "Create A: " << a << endl; }
A(const A& oa) { a_ = oa.a_; cout << "Copy A: " << oa.a_ << endl; }
A(A& oa) { a_ = oa.a_; cout << "Copy A non-const: " << oa.a_ << endl; }
A(const A&& oa) { a_ = oa.a_; cout << "Move A: " << oa.a_ << endl; }
A(A&& oa) { a_ = oa.a_; cout << "Move A non-const: " << oa.a_ << endl; }
~A() { cout << "Del A: " << a_ << ", ptr: " << this << endl; }
int32_t a_;
};
void CreateAs(vector<pair<int32_t, A>>& as) {
as.reserve(3);
for (int32_t i = 0; i < 3; ++i) {
A* a = new A(i*i);
cout << "a ptr: " << &a << endl;
cout << "-----before insert----" << endl;
as.emplace_back(make_pair(i, move(*a)));
cout << "-----after insert-----" << endl;
}
}
void Test() {
vector<pair<int32_t, A>> as;
cout << "-----Create begin----" << endl;
CreateAs(as);
cout << "-----Create end------" << endl;
for (const auto& item : as) {
cout << item.first << "->" << item.second.a_ << endl;
}
}
int main(int32_t argc, char* argv[]) {
Test();
cout << "____end test____" << endl;
return 0;
}
【问题讨论】:
-
make_pair在pair中构造一个A。emplace_back将pair和A移动到向量中。从pair移动的被销毁,同时也销毁了包含的A。 -
为什么不只是
as.emplace_back(i, std::move(*a));?这就是安置的目的。 -
注意:您的
for循环会造成内存泄漏。使用new A(i*i);创建的对象永远不会被销毁,它会参与移动,但move不会销毁您从中移动的对象。 -
@RoyHuang 内存不会被回收。您必须明确地
delete使用new创建的每个指针 -
@RoyHuang 是的,那是你创建的向量中
As 的破坏,而不是你newed 的内存。如果你在for循环的末尾添加一个delete a;,你会看到一组额外的析构函数在运行。