0

我遇到了类似于下面的代码片段的东西,它会引发编译器错误,因为它使用const_iterator. 有没有理由vec.end()instd::copy没有隐式地得到一个const演员?

int main(int argc, char* argv[]) {

    vector<int> vec;
    vec.push_back(20);
    vec.push_back(30);
    vector<int> copy_vec;
    vector<int>::const_iterator i = vec.begin();
    std::copy(i,vec.end(),back_inserter(copy_vec));
    cerr<<copy_vec.size()<<endl;
    return 0;
}
4

3 回答 3

5

不需要std::copy,也不需要一对迭代器。

只需这样做:

vector<int> copy_vec(vec); //use the copy constructor!

你完成了!

至于您的代码为什么会出错,是因为第一个迭代器std::copy是 a const_iterator,但第二个迭代器是iterator. 两者必须是相同的类型,但它们不是,因此模板参数推导失败,因为std::copy它是一个函数模板。

要通过示例理解这一点,请考虑以下简单代码:

template<typename T>
void f(T a, T b) {}

int main()
{
    int a = 100;
    char b = 'A';
    f(a,b);
}

它给出了错误(见ideone):

prog.cpp:8: error: no matching function for call to ‘f(int&, char&)’

它无法编译,因为我们依赖于模板参数推导。由于函数模板中第一个参数和第二个参数的类型完全相同,但我们称这个函数传递a(即int)作为第一个参数,b(即char)作为第二个参数,它不能T从不同类型的参数中唯一地推导!请注意,模板参数推导过程中不考虑转换。

但是,如果我们不依赖模板参数推导,而是显式提供模板参数,那么它会起作用(参见ideone):

f<int>(a,b);  //works!

它的工作原理是不需要T从函数参数中推断出来!

同样,如果您为 提供模板参数std::copy,那么即使您的代码也可以工作(请参阅ideone):

std::copy<vector<int>::const_iterator>(i,vec.end(),back_inserter(copy_vec));
       //^^^^^^^^^^^^^^^^^^^^^^^^^^^^ explicitly provide template argument!

它之所以有效,是因为iterator可以转换为const_iterator,但const_iterator不能转换为iterator这意味着以下内容会出错(请参阅ideone):

std::copy<vector<int>::iterator>(i,vec.end(),back_inserter(copy_vec));
        //^^^^^^^^^^^^^^^^^^^^^ non-const iterator!
于 2011-11-10T05:42:08.670 回答
1

vec是一个非常量向量,因此end将返回一个非常量迭代器。这样的迭代器实际上不能隐式转换为 const 版本,因为它们是单独的类。

相反,使用两个迭代器构造函数:

vector<int> copy_vec(vec.begin(), vec.end());

于 2011-11-10T05:39:35.767 回答
0

我认为这里的问题是 std::copy 被声明为采用三个参数。

前两个是相同的类型,并且您正在传递( const_iterator, vec.end () )- 并且 vec.end() 正在返回一个非常量迭代器(因为 vec 是一个非常量向量)。这会导致编译器拒绝 std::copy 的模板。

如果你有这样的功能:

void doit ( const std::vector<int> &vec, std::vector<int> &out ) {
    std::vector<int>::const_iterator i = vec.begin();
    std::copy(i,vec.end(),back_inserter(out));
    }

然后它将编译并正常工作,因为 vec.end() 将返回一个 const_iterator。或者,如果您使用的是 C++11,则可以调用 vec.cend() 来获取 const_iterator。

于 2011-11-10T05:25:00.593 回答