移动shared_ptr会将移动的shared_ptr设置为nullptr,为什么允许在const_iterator中执行此操作?
std::vector<std::shared_ptr<std::string>> sharedPtrVector;
sharedPtrVector.push_back(std::shared_ptr<std::string>(new std::string("test")));
for (std::vector<std::shared_ptr<std::string>>::const_iterator it = sharedPtrVector.begin(); it != sharedPtrVector.end(); ++it) {
// Not allowed if const_iterator
//*it = nullptr;
// Not allowed if const_iterator
//*static_cast<std::shared_ptr<std::string> *>(&*it) = nullptr;
// Allowed even if const_iterator
std::shared_ptr<std::string> test(std::move(*it));
}
此后,sharedPtrVector处于未定义状态。
答案 0 :(得分:5)
正如评论中所讨论的,std::move
实际上并不执行移动,它只是将迭代器强制转换为rvalue-reference,因此可以从中移动它。在const std::shared_ptr<T>&
的情况下,它将转换为const std::shared_Ptr<T>&&
移动构造函数不接受的std::shared_ptr<T>
,因此它将使用复制构造函数。
这可以通过检查shared_ptr<T>
指向的const_iterator
之后是否为空来确认:
std::vector<std::shared_ptr<std::string>> sharedPtrVector;
sharedPtrVector.emplace_back(std::make_shared<std::string>("test"));
for (auto it = sharedPtrVector.cbegin(); it != sharedPtrVector.cend(); ++it) {
std::shared_ptr<std::string> test(std::move(*it));
if (*it)
std::cout << "*it is not empty\n";
}