【发布时间】:2020-01-15 13:58:29
【问题描述】:
我正在编写一个依赖于向量中的项目的迭代器和一个生成上述迭代器的迭代器工厂。该代码在概念上等同于以下内容:
struct Iter
{
int i = 0;
vector<int> vec;
Iter(const vector<int>& _vec):
vec(_vec)
{
cout << "copied vector of size "<<vec.size()<<" for iterator\n";
}
Iter(vector<int>&& _vec):
vec(move(_vec))
{
cout << "moved vector of size "<<vec.size()<<" for iterator\n";
}
int& operator*() { return vec[i]; }
Iter& operator++() { ++i; return *this; }
bool operator!=(const Iter& _it) const { return false; }
};
struct Factory
{
vector<int> fac_vec;
Factory(const vector<int>& _v):
fac_vec(_v)
{
cout << "copied vector of size " << fac_vec.size() << " for factory\n";
}
Factory(vector<int>&& _v):
fac_vec(move(_v))
{
cout << "moved vector of size "<<fac_vec.size()<<" for factory\n";
}
Iter begin() { return Iter(fac_vec); }
Iter end() { return Iter({}); }
};
int main(){
for(const int i: Factory({1,2,3}))
cout << i << "\n";
return 0;
}
现在,运行这段代码给了我 (g++ 8.3):
moved vector of size 3 for factory [ initialization of the factory with {1,2,3} - moved ]
copied vector of size 3 for iterator [ initialization of the begin-iterator with fac_vec - copied ]
moved vector of size 0 for iterator [ initialization of the end-iterator with {} - moved ]
这有点令人失望,因为我希望最后一个 begin() 会调用 Iter 的 move-constructor,因为工厂在之后立即被销毁(不是吗?)并且编译器拥有所有信息它需要决定这一点。
我想我可以使用std::shared_ptr 做我想做的事,但这会在代码和程序中产生开销。当最后一个 begin() 被调用时,我宁愿告诉编译器 move fac_vec。有没有办法做到这一点?
【问题讨论】:
-
我不认为 Factory 对象在 begin() 被调用后被销毁。它一直持续到 for() 循环完成。
-
是的,我同意。但是,在
begin()之后,向量fac_vec再也不会被触及。它可以很容易地被移动,所以我认为编译器应该能够移动它,我只是不知道如何告诉它。 -
好的,有道理。我认为您需要在调用 Iter() 构造函数时使用 std::move(fac_vec) (下面的答案似乎更详细)。
标签: c++ c++11 move-constructor temporary-objects