为什么在const_iterator中允许移动shared_ptr?

时间:2014-10-12 15:56:17

标签: c++11 iterator const shared-ptr move

移动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处于未定义状态。

1 个答案:

答案 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";
}