meadowlark
meadowlark

Reputation: 23

Using accessors on reference to vector for iteration in C++

I am trying to iterate over a reference to a vector of strings inside a function. The code originally iterated over an internal copy of the vector but I would like to iterate over the original if possible. However, when I try to do so, I get type mismatch problems.

I tried to work with just portions of an iterator by setting and printing it, but I get similar type mismatching for both the initialization and printing with a %s format specifier. Inside gdb, printing the begin accessor works the same for the reference to the vector or a copy of that to its own vector.

Outside:

std::vector<std::string> foo;
foo.pushback('alpha');
foo.pushback('bravo');
func(foo);

Inside with copying:

void func(const std::vector<std::string> &bar){

    std::vector<std::string> barcopy = bar;

    for (std::vector<std::string>::iterator barIt = barcopy.begin(); barIt != barcopy.end(); barIt++){
        //operations with the string inside barcopy
    }
}

Inside without copying:

void func(const std::vector<std::string> &bar){
    for (std::vector<std::string>::iterator barIt = bar.begin(); barIt != bar.end(); barIt++){
        //operations with the string inside bar
    }
}

I expected the reference to behave the same as the copy, but attempting this directly gets me the following when attempting to compile.

error: conversion from 
'__gnu_cxx::__normal_iterator<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >' 
to non-scalar type 
'__gnu_cxx::__normal_iterator<std::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >' 
requested

What type does the begin accessor return when performed on a reference to a vector? How do I go about iterating over this reference without copying?

Upvotes: 2

Views: 410

Answers (2)

catnip
catnip

Reputation: 25388

Because you are passing bar as a const ref, you need to change:

for (std::vector<std::string>::iterator barIt = bar.begin(); barIt != bar.end(); barIt++)

to:

for (std::vector<std::string>::const_iterator barIt = bar.cbegin(); barIt != bar.cend(); barIt++)

or, better still, use a ranged for loop, if all you want is to iterate through the elements in the vector:

for (auto &elem : bar)

Alternatively, change your function signature to void func(std::vector<std::string> &bar) (without the const). The ranged for loop will work in either case.

Upvotes: 7

Blastfurnace
Blastfurnace

Reputation: 18652

Notice that you are taking the parameter as a const reference. The error is due to trying to take a non-const iterator from a const container. You could fix the error by changing your code to: (take note of the iterator type)

for (std::vector<std::string>::const_iterator barIt = bar.begin(); barIt != bar.end(); barIt++){
    //operations with the string inside bar
}

Alternatively, you could use the auto keyword which will deduce the correct iterator type:

for (auto barIt = bar.begin(); barIt != bar.end(); barIt++){
    //operations with the string inside bar
}

Upvotes: 3

Related Questions