Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.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++_Stl_Iterator_Const Iterator - Fatal编程技术网

C++ 如何消除常量迭代器的常量?

C++ 如何消除常量迭代器的常量?,c++,stl,iterator,const-iterator,C++,Stl,Iterator,Const Iterator,作为这个问题的扩展,我还有一个关于常量迭代器的问题。如何删除常量迭代器的常量? 虽然迭代器是指针的一般形式,但是常量迭代器和迭代器是两种不同的东西。因此,我相信,我也不能使用const\u cast将const\u迭代器转换为iterators 一种方法是定义一个迭代器,它移动到const_iterator指向的元素。但这看起来是一个线性时间算法 你知道实现这一点的最佳方法是什么吗?你可以从常量迭代器中减去begin()迭代器以获得常量迭代器指向的位置,然后再将begin()加回到该位置以获得非

作为这个问题的扩展,我还有一个关于常量迭代器的问题。如何删除常量迭代器的常量? 虽然迭代器是指针的一般形式,但是
常量迭代器
迭代器
是两种不同的东西。因此,我相信,我也不能使用
const\u cast
const\u迭代器
转换为
iterator
s

一种方法是定义一个迭代器,它移动到
const_iterator
指向的元素。但这看起来是一个线性时间算法

你知道实现这一点的最佳方法是什么吗?

你可以从常量迭代器中减去begin()迭代器以获得常量迭代器指向的位置,然后再将begin()加回到该位置以获得非常量迭代器。我不认为这对于非线性容器是非常有效的,但是对于线性容器,如vector,这将需要恒定的时间

vector<int> v;                                                                                                         
v.push_back(0);
v.push_back(1);
v.push_back(2);
v.push_back(3);
vector<int>::const_iterator ci = v.begin() + 2;
cout << *ci << endl;
vector<int>::iterator it = v.begin() + (ci - v.begin());
cout << *it << endl;
*it = 20;
cout << *ci << endl;
向量v; v、 推回(0); v、 推回(1); v、 推回(2); v、 推回(3); 向量::常量迭代器ci=v.begin()+2;
cout不幸的是,线性时间是唯一的方法:

iter i(d.begin());
advance (i,distance<ConstIter>(i,ci));
国际热核实验堆一期(d.begin()); 前进(i,距离(i,ci));
iter和CONTISTER适用于typedefs,d是您迭代的容器。

这可能不是您想要的答案,但有些关联

我假设您想要更改迭代器指向的对象。我所做的最简单的方法是const_转换返回的引用

像这样的

    vector<int> v;                                                                                                         
v.push_back(0);
v.push_back(1);
v.push_back(2);
v.push_back(2);
vector<int>::const_iterator ci = v.begin() + 2;
cout << *ci << endl;
*const_cast<int*>(&(*ci)) = 7;
cout << *ci << endl;

const_cast(*it)

您可以将常量迭代器值指针转换为非常量值指针,并直接使用它,如下所示

    vector<int> v;                                                                                                         
v.push_back(0);
v.push_back(1);
v.push_back(2);
v.push_back(2);
vector<int>::const_iterator ci = v.begin() + 2;
cout << *ci << endl;
*const_cast<int*>(&(*ci)) = 7;
cout << *ci << endl;
向量v; v、 推回(0); v、 推回(1); v、 推回(2); v、 推回(2); 向量::常量迭代器ci=v.begin()+2;
cout我相信在设计良好的程序中不需要这种转换

如果需要,请尝试重新设计代码

作为解决方法,您可以使用以下方法:

typedef std::vector< size_t > container_type;
container_type v;
// filling container code 
container_type::const_iterator ci = v.begin() + 3; // set some value 
container_type::iterator i = v.begin();
std::advance( i, std::distance< container_type::const_iterator >( v.begin(), ci ) );
typedef std::vector容器类型;
v型集装箱;
//灌装容器代码
容器类型::常量迭代器ci=v.begin()+3;//设定一些价值
容器类型::迭代器i=v.begin();
std::advance(i,std::distance(v.begin(),ci));

但我认为,有时这种转换是不可能的,因为您的算法无法访问容器。

在您上一篇文章的答案中,包括我在内的一些人建议使用const_迭代器,而不是出于与性能无关的原因。可读性,从设计板到代码的可追溯性。。。使用常量迭代器提供对非常量元素的变异访问比根本不使用常量迭代器糟糕得多。您正在将代码转换成只有您自己才能理解的东西,设计更糟糕,维护更困难。使用const来丢弃它比根本不使用const要糟糕得多

<>如果你确信你想要它,C++的好/坏部分是你总能得到足够的绳子来挂你自己。如果您打算使用const_迭代器来解决性能问题,您应该重新考虑它,但如果您仍然想一脚踢开。。。好的C++可以提供你的选择武器。 首先,最简单的是:如果您的操作将参数作为常量(即使在内部应用const_cast),我认为它应该直接在大多数实现中工作(即使它可能是未定义的行为)

如果无法更改函子,则可以从任意一方解决此问题:在常量迭代器周围提供一个非常量迭代器包装器,或者在非常量函子周围提供一个常量函子包装器

Iterator façade,漫长的道路:

template <typename T>
struct remove_const
{
    typedef T type;
};
template <typename T>
struct remove_const<const T>
{
    typedef T type;
};

template <typename T>
class unconst_iterator_type
{
    public:
        typedef std::forward_iterator_tag iterator_category;
        typedef typename remove_const<
                typename std::iterator_traits<T>::value_type
            >::type value_type;
        typedef value_type* pointer;
        typedef value_type& reference;

        unconst_iterator_type( T it )
            : it_( it ) {} // allow implicit conversions
        unconst_iterator_type& operator++() {
            ++it_;
            return *this;
        }
        value_type& operator*() {
            return const_cast<value_type&>( *it_ );
        }
        pointer operator->() {
            return const_cast<pointer>( &(*it_) );
        }
        friend bool operator==( unconst_iterator_type<T> const & lhs,
                unconst_iterator_type<T> const & rhs )
        {
            return lhs.it_ == rhs.it_;
        }
        friend bool operator!=( unconst_iterator_type<T> const & lhs,
                unconst_iterator_type<T> const & rhs )
        {
            return !( lhs == rhs );
        }
    private:
        T it_;  // internal (const) iterator
};
模板
结构删除常量
{
T型;
};
模板
结构删除常量
{
T型;
};
模板
类未约束迭代器类型
{
公众:
typedef std::forward_iterator_tag iterator_category;
typedef typename删除\u const<
typename std::迭代器特征::值类型
>::类型值\u类型;
typedef值\u type*指针;
类型定义值\u类型和参考;
无约束迭代器类型(T it)
:it_(it){}//允许隐式转换
无约束迭代器类型和运算符++(){
++它!;
归还*这个;
}
值类型和运算符*(){
返回const_cast(*it_u);
}
指针运算符->(){
返回const_cast(&(*it_));
}
friend bool运算符==(未约束迭代器类型常量和lhs,
无约束迭代器(类型常量和rhs)
{
返回lhs.it==rhs.it;
}
friend bool运算符!=(未约束迭代器类型常量和lhs,
无约束迭代器(类型常量和rhs)
{
返回!(lhs==rhs);
}
私人:
T it_;//内部(常量)迭代器
};

关于优先使用迭代器而不是常量迭代器的问题回答了这个问题。Visage的答案是C++11之前唯一安全的替代方案,但实际上对于实现良好的随机访问迭代器是恒定时间,对于其他迭代器是线性时间。

在C++11中有一个具有恒定时间复杂性的解决方案:对于任何序列、关联或无序关联容器(包括所有标准库容器),您可以使用空范围调用范围擦除成员函数:

template <typename Container, typename ConstIterator>
typename Container::iterator remove_constness(Container& c, ConstIterator it)
{
    return c.erase(it, it);
}
模板
typename容器::迭代器移除常量(容器&c,迭代器it)
{
返回c.erase(它,它);
}
范围擦除成员函数有一对
常量迭代器