使用模板函数和迭代器显示vector中的元素

#include <iostream>
#include <vector>
#include <iterator>

using namespace std;

template<typename T>
void factorial(vector<T> ivec, vector<T>::iterator iter) {
    while (iter != ivec.end()) {
        cout << *iter << endl;
        ++iter;
    }
}

int main() {

    vector<int> ivec = { 1,2,3,4,5,6,7 };
    factorial(ivec, ivec.begin());

    return 0;
}

在VS 2017中他的报错信息如下:

警告    C4346    “std::vector<T,std::allocator<_Ty>>::iterator”: 依赖名称不是类型    practice_needForCpp11    d:\practice_needforcpp11\practice_needforcpp11\源.cpp    8    
错误    C2061    语法错误: 标识符“iterator”    practice_needForCpp11    d:\practice_needforcpp11\practice_needforcpp11\源.cpp    8    
错误    C2672    “factorial”: 未找到匹配的重载函数    practice_needForCpp11    d:\practice_needforcpp11\practice_needforcpp11\源.cpp    18    
错误    C2780    “void factorial(std::vector<T,std::allocator<_Ty>>)”: 应输入 1 个参数,却提供了 2 个    practice_needForCpp11    d:\practice_needforcpp11\practice_needforcpp11\源.cpp    18    

请教各位一下这里出了什么问题~谢谢了~~

阅读 5.6k
3 个回答

在Vs2008上运行,会报错。
错误的原因有:
(1)vector<int> ivec = { 1,2,3,4,5,6,7 }; vector不能直接这样初始化赋值。可以用这样来替换

vector<int> ivec;
    for(int i=1;i<8;i++){
        ivec.push_back(i);
    }

(2)函数写的很不好,直接用这样写就行了,根本没必要传ivec.begin()给函数。因为你已经传了ivec给函数,函数就会得到ivec的所有信息,不必画蛇添足。

#include "iostream"
#include <vector>
using namespace std;
void factorial(vector<int> ivec) {
    vector<int>::iterator it;
    for(it=ivec.begin();it!=ivec.end();it++)
    cout<<*it<<endl;
}

int main()
{
    vector<int> ivec;
    for(int i=1;i<8;i++){
        ivec.push_back(i);
    }
    factorial(ivec);

    return 0;
}

如果你非要画蛇添足的做法,可以这样写,至于为什么要加个&符号,是因为不引用的的话就会新建个vector,那么新建的vector里面是没有数据的,所以就肯定错了。

#include "iostream"
#include <vector>
using namespace std;
void factorial(vector<int> &ivec,vector<int>::iterator iter) {
    vector<int>::iterator it;
    for(it=iter;it!=ivec.end();it++)
    cout<<*it<<endl;
}

int main()
{
    vector<int> ivec;
    for(int i=1;i<8;i++){
        ivec.push_back(i);
    }
    factorial(ivec,ivec.begin());
    
    return 0;
}

改动两个位置,

改动前:void factorial(vector<T> ivec, vector<T>::iterator iter)
改动后:void factorial(vector<T> & ivec, typename vector<T>::iterator iter)

先说第二个改动位置,typename是干嘛的?参考http://blog.csdn.net/laojiu_/...

第一个改动位置,我也说不清,不加引用的话,在与end()比较的时候vs报错类型不匹配,这个我也没搞清楚。。。(多谢奔跑如风,恍然大悟,因为ivec是值传递,与原先的对象完全是两个,只是它们内容相同而已)

一、如果 ivec 不加 & ,则采用传值方式,ivec 是原传来的参数的一份拷贝,而第二个参数 iter ,传过来的迭代器是指向 ivec 原传来的参数的迭代位置。与拷贝后的 ivec.end() 比较时很可能会产生越界访问,导致程序崩溃。

二、 void factorial(vector<T> ivec, vector<T>::iterator iter) ,编译错误则如 @刘毅 所说的,涉及一个叫 nested dependent name(嵌套依赖名字) 的概念。

三、其实这个函数还有几种写法,例如

// 代码环境: Cygwin、g++ 5.4.0

// c++ 98
template<typename T>
void factorial(vector<T> &ivec) {
    typename vector<T>::iterator iter = ivec.begin();
    while ( iter != ivec.end()) {
        cout << *iter << endl;
        ++iter;
    }
}

// C++ 11 范围for(range for)
template<typename T>
void factorial_C11(vector<T> &ivec) {
    for( auto iter : ivec)
        cout << iter << endl;
}

// 在 C++ 14 标准中 auto 可以用于参数列表的特性
template<typename T>
void factorial_C14(vector<T> &ivec, auto iter) {
    while ( iter != ivec.end()) {
        cout << *iter << endl;
        ++iter;
    }
}

比较喜欢范围 for , 简单明了。

对,列表初始化 vector , 在 C++ 11 中已经支持了,但, 好像 VS 要到 2010 还是 2012 版本才相对完整对支持 C++ 11 标准。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题