gpt4 book ai didi

c++ - 对于具有线性存储的容器,可以使用原始指针而不是具有 STL 算法的迭代器吗?

转载 作者:IT老高 更新时间:2023-10-28 22:17:16 27 4
gpt4 key购买 nike

我有一个自定义 vector 容器,它在内部存储项目一个线性数组。昨晚,我试图为我的类实现自定义迭代器,以便能够将它们与 STL 算法一起使用。我取得了一些成功,您可以在这里看到:

Live example with custom iterators

这样做时,我发现我只能将原始指针传递给 STL 算法,它们似乎工作正常。这是没有任何迭代器的示例:

#include <cstddef>
#include <iostream>
#include <iterator>
#include <algorithm>

template<typename T>
class my_array{
T* data_;
std::size_t size_;

public:

my_array()
: data_(NULL), size_(0)
{}
my_array(std::size_t size)
: data_(new T[size]), size_(size)
{}
my_array(const my_array<T>& other){
size_ = other.size_;
data_ = new T[size_];
for (std::size_t i = 0; i<size_; i++)
data_[i] = other.data_[i];
}
my_array(const T* first, const T* last){
size_ = last - first;
data_ = new T[size_];

for (std::size_t i = 0; i<size_; i++)
data_[i] = first[i];
}

~my_array(){
delete [] data_;
}
const my_array<T>& operator=(const my_array<T>& other){
size_ = other.size_;
data_ = new T[size_];
for (std::size_t i = 0; i<size_; i++)
data_[i] = other.data_[i];
return other;
}
const T& operator[](std::size_t idx) const {return data_[idx];}
T& operator[](std::size_t& idx) {return data_[idx];}
std::size_t size(){return size_;}

T* begin(){return data_;}
T* end(){return data_+size_;}
};

template<typename T>
void print(T t) {
std::cout << t << std::endl;
}

int main(){


typedef float scalar_t;
scalar_t list [] = {1, 3, 5, 2, 4, 3, 5, 10, 10};
my_array<scalar_t> a(list, list+sizeof(list)/sizeof(scalar_t));

// works!
for (scalar_t* it = a.begin(), *end = a.end();
it != end; ++it)
std::cout << ' ' << *it;
std::cout << std::endl;

// works!
std::for_each(a.begin(), a.end(), print<scalar_t>);
std::cout << std::endl;

// works!
my_array<int> b(a.size());
std::copy(a.begin(), a.end(), b.begin());

// works!
scalar_t* end = std::remove(a.begin(), a.end(), 5);
std::for_each(a.begin(), end, print<scalar_t>);
std::cout << std::endl;

// works!
std::random_shuffle(a.begin(), end);
std::for_each(a.begin(), end, print<scalar_t>);
std::cout << std::endl;

// works!
std::cout << "Counts of 3 in array = " << std::count(a.begin(), end, 3) << std::endl << std::endl;

// works!
std::sort(a.begin(), end);
std::for_each(a.begin(), end, print<scalar_t>);
std::cout << std::endl;

// works!
if (!std::binary_search(a.begin(), a.end(), 5))
std::cout << "Removed!" << std::endl;

return 0;
}

Live example without iterators

我的问题如下:

  1. 这是否总是适用于具有线性存储的容器?我知道这不适用于例如链表。
  2. 如果它们确实在这种情况下工作,我为什么还要经历实现迭代器的麻烦呢?我知道迭代器如何泛化我的代码等等,但是如果这个简单的数组 我所需要的,那么我看不到重点。
  3. 如果这种方法始终有效,我正在做的事情有哪些负面问题?一方面,我可以看到我正在破坏数据封装。

最佳答案

基于运算符重载的迭代器的特性之一是指针已经是随机访问的迭代器。在 STL 的早期,这是一个重大的设计胜利,因为它使算法更容易与现有代码一起使用(以及使程序员更熟悉界面)。包装一个数组是完全合理的,添加 typedef T* 迭代器; typedef const T* const_iterator,从你的 begin()&array[size] 返回 &array[0] 从你的 >end(),然后将您的容器与任何基于迭代器的算法一起使用。正如您已经意识到的那样,这适用于任何元素在内存中连续的容器(例如数组)。

如果满足以下条件,您可能会实现“真正的”迭代器:

  • 您有一个不同形状的容器(例如树或列表);
  • 您希望能够在不使迭代器失效的情况下调整数组大小;
  • 您想在迭代器使用中添加调试检查,例如检查迭代器是否在失效后或容器被删除后使用,或边界检查;
  • 您想引入类型安全,并确保人们不会意外地将任意 T* 分配给 my_array::iterator

我想说,仅此最后一个优势就非常值得为其编写一个微不足道的包装类。如果你不利用 C++ 的类型系统让不同种类的东西有不同的类型,你还不如切换到 Javascript :-)

关于c++ - 对于具有线性存储的容器,可以使用原始指针而不是具有 STL 算法的迭代器吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16445957/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com