【问题标题】:std::vector<std::string> insert empty string insteadstd::vector<std::string> 改为插入空字符串
【发布时间】:2016-11-21 14:13:13
【问题描述】:

在 Visual Studio 2013 中,我创建了一个 std::vector 并在其中存储了一些字符串。然后我想在向量中复制一些字符串并将它们附加到末尾(假设将它们移动到末尾,插入后会擦除),但是使用插入方法,我在末尾只看到了空字符串,非常奇怪的。我用一些简单的测试代码重现了它,

std::vector<std::string> v;
std::string s = "0";
for (int i = 0; i < 7; ++i)
{
    s[0] = '0' + i; 
    v.push_back(s);
}
v.insert(v.end(), v.begin(), v.begin() + 3);
for (std::string& s : v) 
    std::cout << "\"" << s.c_str() << "\" ";

我得到的是 “0”“1”“2”“3”“4”“5”“6”“”“”“”

我调试了insert方法,在vector类的_Insert(..)方法里面,做了一些内存的重新分配,内存的移动/移动等等。

第一个 _Umove 调用将所有 7 个字符串移动到新分配的内存,我认为调用了 std::move,旧内存留下了一些空字符串。

然后 _Ucopy 方法尝试复制 3 个项目,但从旧内存中,结果附加了 3 个空字符串。 还有另一个 _Umove 电话,我不知道那是为了什么。毕竟,旧的内存被释放,新的内存被附加到向量上。

使用像 int 这样的标量类型不会产生错误的输出,因为内存被复制,没有调用 std::move。

我在这里做错了什么,还是 MS Visual Studio 的 STL 错误?

【问题讨论】:

    标签: c++11 stl stdvector stdstring


    【解决方案1】:

    来自this std::vector::insert reference:

    如果新的size() 大于旧的capacity(),则会导致重新分配。如果新的size() 大于capacity(),则所有迭代器和引用都无效

    [强调我的]

    您在使用迭代器迭代向量时向向量添加元素。由于这可能导致向量被重新分配,因此您的迭代器将失效。这将导致未定义的行为。

    【讨论】:

    • 据我了解,重新分配会导致迭代器和引用失效,这应该在插入返回后发生。任何迭代器和对向量的引用都无效,但这发生在调用期间,这对我来说很奇怪。我尝试在插入之前保留一些空间,然后它可以工作。这只是一种解决方法。稍后我将尝试使用其他编译器。
    • @TigerHwang 您将两个迭代器传递给insert 函数。只要insert 函数为新元素腾出空间,您传递的那些迭代器就会变得无效。使用其他编译器不会解决您的问题。保留空间是唯一的解决方案。
    • 我的目标是将向量中的一些字符串移到最后,所以我尝试了另一种方法 std::move(v.begin(), v.begin() + 3, v.end( ))。由于迭代器+偏移超出范围,这会导致断言失败。使用 std::move(v.begin(), v.begin() + 3, v.end() - 3),它不会失败,但结果不是我想要的。有什么建议吗?
    • @TigerHwang 在这种情况下,我建议使用一个普通的 for 循环,迭代 3 次。在循环中获取第一个元素的value,去掉第一个元素,在后面加上value。
    • 谢谢,我只记得 std 中的 rotate 方法应该可以解决问题。
    猜你喜欢
    • 1970-01-01
    • 2011-05-26
    • 2011-01-14
    • 2011-06-04
    • 1970-01-01
    • 2013-08-18
    • 1970-01-01
    • 1970-01-01
    • 2018-05-31
    相关资源
    最近更新 更多