Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 擦除()向量中的元素不会';行不通_C++_Vector - Fatal编程技术网

C++ 擦除()向量中的元素不会';行不通

C++ 擦除()向量中的元素不会';行不通,c++,vector,C++,Vector,我有一个向量。我需要删除其中的最后3个元素。 描述了这个逻辑。程序崩溃了。可能是什么错误 vector<float>::iterator d = X.end(); for (size_t i = 1; i < 3; i++) { if (i == 1) X.erase(d); else X.erase(d - i); } vector::迭代器d=X.end(); 对于(大小i=1;i < P> >把端()//> >迭代器传递给

我有一个向量。我需要删除其中的最后3个元素。 描述了这个逻辑。程序崩溃了。可能是什么错误

vector<float>::iterator d = X.end();
    for (size_t i = 1; i < 3; i++) {
        if (i == 1) X.erase(d);
        else X.erase(d - i);
    }
vector::迭代器d=X.end();
对于(大小i=1;i<3;i++){
如果(i==1)X,则删除(d);
否则X.erase(d-i);
}
这句话

    if (i == 1) X.erase(d);
具有未定义的行为

此语句尝试仅删除最后一个元素之前的元素

    else X.erase(d - i);
因为你有一个只有两次迭代的循环

for (size_t i = 1; i < 3; i++) {

如果向量中至少有3项,删除最后3项很简单——只需调用3次:


您可以使用
反向迭代器

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<float> X = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6};

    // start the iterator at the last element
    vector<float>::reverse_iterator rit = X.rbegin();

    // repeat 3 times
    for(size_t i = 0; i < 3; i++)
    {
        rit++;
        X.erase(rit.base());
    }

    // display all elements in vector X
    for(float &e: X)
        cout << e << '\n';

    return 0;
}
#包括
#包括
使用名称空间std;
int main()
{
向量X={1.1,2.2,3.3,4.4,5.5,6};
//在最后一个元素处启动迭代器
向量::反向迭代器rit=X.rbegin();
//重复3次
对于(大小i=0;i<3;i++)
{
rit++;
X.擦除(rit.base());
}
//以矢量X显示所有元素
用于(浮球和e:X)

coutfrom的
end()
定义如下:

返回一个迭代器,该迭代器引用向量容器中结束元素的过去部分。 略低于:

它不指向任何元素,因此不应取消引用。 换句话说,该向量没有end()指向的元素。通过erase()方法取消对该非元素的引用,您可能正在更改不属于该向量的内存。因此,从此以后可能会发生丑陋的事情

通常是用C++约定,将区间描述为[低,高],区间中包含“低”值,间隔中的“高”值<强>排除< /强>。< / P > < P> >把<代码>端()//> >迭代器传递给1-参数超载是不确定的行为。

使位于指定元素处和之后的迭代器无效,使
d
在第一次循环迭代后无效

std::vector
有一个2参数
erase()
重载,它接受一系列要删除的元素。您根本不需要手动循环:

if(X.size()>=3)
擦除(X.end()-3,X.end());
问题中的一条评论(现已删除)指出“迭代器没有-运算符”。然而,以下代码在
MSVC
clang cl
中编译并工作,标准设置为
C++17
C++14

#包括
#包括
int main()
{
std::向量X{1.1f,2.2f,3.3f,4.4f,5.5f,6.6f};
对于(auto f:X)std::cout首先,
X.end()
不会将迭代器返回到向量的最后一个元素,而是返回一个迭代器到向量的最后一个元素之后的元素,这是向量实际上不拥有的元素,这就是为什么当您尝试使用
X.erase(d)
删除它时程序崩溃的原因

相反,如果向量至少包含3个元素,则可以执行以下操作:

X.erase( X.end() - 3, X.end() );
它将转到最后一个元素的第三个,并删除其后的每个元素,直到到达
X.end()


编辑:只是为了澄清,
X.end()
是一个指定为具有有效的
-
操作的函数,该操作返回另一个LegacyRandomAccessIterator。

这里的杀手是
d
实际上并不存在。它是一个超过end canary值的函数,只能用于查找
向量的结尾。您无法删除它。接下来,只要删除一个迭代器,它就消失了。你不能在事后安全地将它用于任何事情,包括
d-i
。我认为它是有效的,因为向量的迭代器是随机访问的,而
-
是为这些迭代器类型定义的。@PaulMcKenzie确实是一个clang静态分析器(对标准来说可能非常严格)没有给出任何警告。即使没有为迭代器定义
运算符-
,也可以使用or。
#include <vector>
#include <iostream>

int main() 
{
    std::vector<float> v = { 1, 2, 3, 4, 5 };
    for (int i = 0; i < 3 && !v.empty(); ++i)
       v.pop_back();

    for ( const auto &item : v ) std::cout << item << ' ';
        std::cout << '\n';
}
1 2
#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<float> X = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6};

    // start the iterator at the last element
    vector<float>::reverse_iterator rit = X.rbegin();

    // repeat 3 times
    for(size_t i = 0; i < 3; i++)
    {
        rit++;
        X.erase(rit.base());
    }

    // display all elements in vector X
    for(float &e: X)
        cout << e << '\n';

    return 0;
}
X.erase( X.end() - 3, X.end() );