使用智能指针的擦除习语

erase-remove idiom with smart pointers

本文关键字:擦除 习语 指针 智能      更新时间:2023-10-16

我需要能够从向量中删除元素,并决定研究擦除-删除习惯用法,这是一种来自c++标准库的算法,比手工编写的循环更可取。我还想使用智能指针的向量,而不是原始指针。

我发现了很多关于擦除习语的帖子,其中相当一部分实际上建议使用智能指针。按照这个建议,我写了3个可行的擦除习语的例子,我复制在下面的输出前面:无指针,原始指针和智能指针。注意智能指针所需的三重解引用。

我的问题:这是一个很好的实现擦除-删除习语与智能指针或有一些…聪明吗?谢谢你的关心。

int向量:1 1 3
Vector of int: 3


int型智能指针的向量:1 1 3
int型智能指针的向量:1 3

#include <windows.h>
#include <algorithm>
#include <iostream>
#include <vector>
#include <memory>
#include <string>
std::vector<int> intVector;
std::vector<int*> intVectorPointers;
std::vector<std::shared_ptr<int*>> intVectorSmartPointers;
void printVector(std::vector<int> intV){
    std::cout << "vector of int: ";
    for (std::vector<int>::const_iterator it = intV.begin(); it != intV.end(); it++)
    std::cout << ' ' << *it;
    std::cout << 'n';
}
void printVectorPointers(std::vector<int*> intVPointers){
    std::cout << "vector of pointers of int: ";
    for (std::vector<int*>::const_iterator it = intVPointers.begin(); it != intVPointers.end(); it++)
    std::cout << ' ' << **it;
    std::cout << 'n';
}
void printVectorSmartPointers(std::vector<std::shared_ptr<int*>> intVSmartPointers) {
    std::cout << "vector of smart pointers of int: ";
    for (std::vector<std::shared_ptr<int*>>::const_iterator it = intVSmartPointers.begin(); it != intVSmartPointers.end(); it++)
    std::cout << ' ' << ***it;
    std::cout << 'n';
}

int main(int argc, char* argv[]) {
    int int1 = 1;
    int int2 = 1;
    int int3 = 3;
    int *intPointer1 = &int1;
    int *intPointer2 = &int2;
    int *intPointer3 = &int3;
    std::shared_ptr<int*> intSmartPointer1 = std::make_shared<int*>(intPointer1);
    std::shared_ptr<int*> intSmartPointer2 = std::make_shared<int*>(intPointer2);
    std::shared_ptr<int*> intSmartPointer3 = std::make_shared<int*>(intPointer3);
    intVector.push_back(int1);
    intVector.push_back(int2);
    intVector.push_back(int3);
    intVectorPointers.push_back(intPointer1);
    intVectorPointers.push_back(intPointer2);
    intVectorPointers.push_back(intPointer3);
    intVectorSmartPointers.push_back(intSmartPointer1);
    intVectorSmartPointers.push_back(intSmartPointer2);
    intVectorSmartPointers.push_back(intSmartPointer3);
    printVector(intVector);
    intVector.erase(std::remove(intVector.begin(), intVector.end(), int1), intVector.end());
    printVector(intVector);
    printVectorPointers(intVectorPointers);
    intVectorPointers.erase(std::remove(intVectorPointers.begin(), intVectorPointers.end(), intPointer1), intVectorPointers.end());
    printVectorPointers(intVectorPointers);
    printVectorSmartPointers(intVectorSmartPointers);
    intVectorSmartPointers.erase(std::remove(intVectorSmartPointers.begin(), intVectorSmartPointers.end(), intSmartPointer1), intVectorSmartPointers.end());
    printVectorSmartPointers(intVectorSmartPointers);;
    Sleep(50000);
    return 0;
}

正如其他人指出的那样,除了删除本身之外,代码还有其他问题。

然而,std::remove_if()失败的原因是因为您搜索intPointer1并删除了一个1指针,而不是指向数字1的指针。

你没有说你是否可以访问c++ 11或更好的版本,希望你可以。您可以编写一个lambda来实现:

intVectorPointers.erase(
    std::remove_if(
        intVectorPointers.begin(),
        intVectorPointers.end(),
        [](auto const & p) { return *p == 1; }),
    intVectorPointers.end());

我没有测试过你的整个代码,但类似的东西应该工作。(这是假设你修复你的指针和*p实际上指向数据,而不是另一个指针,在你的例子中,我很确定这不是你想要的。)

所以它可以帮助其他人,下面是一个带有智能指针的擦除-删除习语的干净版本。关于你的评论,不再有指针的指针,唯一指针而不是共享指针,remove_if()而不是remove()

#include <windows.h>
#include <algorithm>
#include <iostream>
#include <vector>
#include <memory>
void printVectorSmartPointers(std::vector<std::unique_ptr<int>> &vSmartPointers) {
    std::cout << "vector of smart pointers of int: ";
    for (std::vector<std::unique_ptr<int>>::const_iterator it = vSmartPointers.begin(); it != vSmartPointers.end(); it++)
    std::cout << ' ' << **it;
    std::cout << 'n';
}

int main(int argc, char* argv[]) {
    std::unique_ptr<int> smartPointer1 = std::make_unique<int>(1);
    std::unique_ptr<int> smartPointer2 = std::make_unique<int>(1);
    std::unique_ptr<int> smartPointer3 = std::make_unique<int>(3);
    std::vector<std::unique_ptr<int>> vectorSmartPointers;
    vectorSmartPointers.push_back(std::move(smartPointer1));
    vectorSmartPointers.push_back(std::move(smartPointer2));
    vectorSmartPointers.push_back(std::move(smartPointer3));
    printVectorSmartPointers(vectorSmartPointers);
    vectorSmartPointers.erase(
        std::remove_if(
        vectorSmartPointers.begin(),
        vectorSmartPointers.end(),
        [](std::unique_ptr<int> const &p) { return *p == 1; }),
        vectorSmartPointers.end());
    printVectorSmartPointers(vectorSmartPointers);
    Sleep(50000);
    return 0;
}