| 网站首页 | 业界新闻 | 群组 | 交易 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
共有 448 人关注过本帖
标题:用remove去除iterator中的const属性问题
只看楼主 加入收藏
花脸
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:7
帖 子:775
专家分:778
注 册:2017-1-4
结帖率:95.33%
  已结贴   问题点数:20  回复次数:13   
用remove去除iterator中的const属性问题
#include <iostream>
#include <type_traits>
using namespace std;

int main()
{
    string s="123456";
    string::iterator it=remove_const<s.begin()>::type ;
    return 0;
}
s.begin()返回一个临时变量,是一个右值,它不能赋值给一个非const的引用:所以我想要把他的const属性去掉。


[此贴子已经被作者于2018-12-24 22:34编辑过]

2018-12-24 22:30
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:291
帖 子:6172
专家分:35580
注 册:2011-1-18
  得分:10 
看不懂你想干什么?
程序代码:
#include <iostream>
using namespace std;

int main()
{
    string s = "123456";
    string::iterator itor = s.begin();
}

2018-12-25 08:21
花脸
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:7
帖 子:775
专家分:778
注 册:2017-1-4
  得分:0 
回复 2楼 rjsp
因为s.begin()返回的值不是带有const属性吗。想把s.begin()只用的const属性去掉。
2018-12-25 12:46
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:291
帖 子:6172
专家分:35580
注 册:2011-1-18
  得分:0 
以下是引用花脸在2018-12-25 12:46:07的发言:

因为s.begin()返回的值不是带有const属性吗。
不是
begin() 返回 string::iterator
begin() const 返回 string::const_iterator
2018-12-25 13:00
花脸
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:7
帖 子:775
专家分:778
注 册:2017-1-4
  得分:0 
#include <iostream>
#include <type_traits>
using namespace std;

void f(string::iterator &it)
{
    ++it;
}
int main()
{
    string s="123456";
    f(s.begin());//这行出错,
    return 0;
}
[Error] invalid initialization of non-const reference of type 'std::basic_string<char>::iterator& {aka __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&}' from an rvalue of type 'std::basic_string<char>::iterator {aka __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >}'

[Note] in passing argument 1 of 'void f(std::basic_string<char>::iterator&)'
我百度的原因说是因为s.begin()返回的iterator带const,把const属性去掉即可。https://blog.csdn.net/wwjue/article/details/52292166

在STL中,我们能见到很多函数的形参都是iterator的传值,而不是传引用。
这是因为我们通常这么用:
void print_vector(vector<int>::iterator beg, vector<int>::itertor end);
while(beg != end) { cout << *beg++ << endl; }
print_vector(v.begin(), v.end());
这里形参如果是引用的话,则编译时会报错,因为v.begin()返回的是一个临时变量,是一个右值,它不能赋值给一个非const的引用:
error: invalid initialization of non-const reference of type 'std::vector<int>::iterator& {aka __gnu_cxx::__normal_iterator<int*, std::vector<int> >&}' from an rvalue of type 'std::vector<int>::iterator {aka __gnu_cxx::__normal_iterator<int*, std::vector<int> >}'
但可以赋值给const 引用;即如果print_vector的形参是const的iterator,就可以传v.begin()给它。但这样一来,在函数体内就不能做++,--或任何修改该iterator的操作了。
这就是iterator一般用传值的原因。
类似的道理,函数的返回值通常不能传给一个非const的引用,因为函数返回值通常也是一个临时变量,是一个右值。
int f() { return 1; }
int &ri1 = f();            //error: invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int'
const int &ri2 = f();   // OK
2018-12-25 19:35
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:291
帖 子:6172
专家分:35580
注 册:2011-1-18
  得分:0 
不可以 non-const 引用一个临时对象
而非 begin() 返回了const类型
2018-12-25 20:13
Jonny0201
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:36
帖 子:448
专家分:2251
注 册:2016-11-7
  得分:10 
5 楼那个例子, 没有那么干的
一个函数需要迭代器都是需要迭代器底层的内容, 而不是单单需要迭代器
你没有理解 STL 使用的迭代器模式是为了什么
程序代码:
void func(std::string::iterator begin, std::string::iterator end) {
    while(begin != end) {
        //...
    }
}

这才是迭代器该做的事情
需要迭代器的函数都是对迭代器底层的内容干些什么, 而不是对迭代器干些什么
另外, string::begin() 返回的是一个纯右值
可以接受它的只有 string::iterator && 或者 string::iterator 或者 const string::iterator &

[此贴子已经被作者于2018-12-25 20:28编辑过]

2018-12-25 20:27
花脸
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:7
帖 子:775
专家分:778
注 册:2017-1-4
  得分:0 
回复 6楼 rjsp
是不是没法在函数的参数列表里调用iterator的引用了?例如:
void f(string::iterator &it)
{
    ++it;
}
2018-12-25 20:27
Jonny0201
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:36
帖 子:448
专家分:2251
注 册:2016-11-7
  得分:0 
对于 string::iterator 和 string::const_iterator
对他们的 const 限定是假的
他们没有 const 限定
string::iterator 的原型在 libcpp 里面是 __wrap_iterator<char *>
string::const_iterator 的原型是 __wrap_iterator<const char *>
想要从 string::const_iterator 转为 string::iterator 需要 reinterpret_cast 帮忙
程序代码:
#include <iostream>

using namespace std;
int main(int argc, char *argv[]) {
    string str {"12345"};
    auto const_iterator {str.cbegin()};
    auto non_const_iterator {*reinterpret_cast<string::iterator *>(&const_iterator)};
    while(non_const_iterator != str.cend()) {
        ++*non_const_iterator;
        ++non_const_iterator;
    }
    cout << str << endl;     //23456
}
2018-12-25 20:34
Jonny0201
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:36
帖 子:448
专家分:2251
注 册:2016-11-7
  得分:0 
回复 8楼 花脸
这个就相当于 C 的指针, 有一个左值就行了
程序代码:
#include <iostream>

using namespace std;
void func(string::iterator &it) {
    ++it;
}
int main(int argc, char *argv[]) {
    string str {"12345"};
    auto iterator {str.begin()};
    func(iterator);
}
2018-12-25 20:37







关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.062196 second(s), 8 queries.
Copyright©2004-2019, BCCN.NET, All Rights Reserved