开发者

Shorter way to get an iterator for a std::vector

开发者 https://www.devze.com 2023-04-06 18:02 出处:网络
Lets say that I have got a vector like this. std::vector<a_complicated_whatever_identifier *> *something

Lets say that I have got a vector like this.

std::vector<a_complicated_whatever_identifier *> *something
    = new std::vector<a_complicated_whatever_identifier *>;
// by the way, is this the right way to do this?

Now I want to get an iterator for this... so I would do this like this.

std::vector<a_complicated_whatever_identifier *>::iterator iter;

But I find it a little too much for my code. I wonder, is there any more, brief way to ask for an iterator regardless of the type?

I was thinking in something like.

something::iterator iter;
    // OK, don’t laugh at me, I am still beginning with C++

Well, it obviously fail, but I guess you get t开发者_如何学编程he idea. How to accomplish this or something similar?


You would typically give your containers sensible typedefs, and then it's a breeze:

typedef std::pair<int, Employee> EmployeeTag;
typedef std::map<Foo, EmployeeTag> SignInRecords;

for (SignInRecords::const_iterator it = clock_ins.begin(); ... )
           ^^^^^^^^^^^^^^^^^

Usually, having a handy typedef for the container is more practical and self-documenting that an explicit typedef for the iterator (imagine if you're changing the container).

With the new C++ (11), you can say auto it = clock_ins.cbegin() to get a const-iterator.


Use a typedef.

typedef std::vector<complicated *>::iterator complicated_iter

Then set them like this:

complicated_iter begin, end;


In C++11 you'll be able to use auto.

auto iter = my_container.begin();

In the meantime just use a typedef for the vector:

typedef std::vector<a_complicated_whatever_identifier *> my_vector;
my_vector::iterator iter = my_container.begin();


You should rarely have much need/use for defining an iterator directly. In particular, iterating through a collection should normally be done by a generic algorithm. If there's one already defined that can do the job, it's best to use it. If there's not, it's best to write your own algorithm as an algorithm. In this case, the iterator type becomes a template parameter with whatever name you prefer (usually something referring at least loosely to the iterator category):

template <class InputIterator>
void my_algorithm(InputIterator start, InputIterator stop) { 
    for (InputIterator p = start; p != stop; ++p) 
        do_something_with(*p);
}

Since they've been mentioned, I'll point out that IMO, typedef and C++11's new auto are (at least IMO) rarely a good answer to this situation. Yes, they can eliminate (or at least reduce) the verbosity in defining an object of the iterator type -- but in this case, it's basically just treating the symptom, not the disease.

As an aside, I'd also note that:

  1. A vector of pointers is usually a mistake.
  2. Dynamically allocating a vector is even more likely a mistake.

At least right off, it looks rather as if you're probably accustomed to something like Java, where you always have to use new to create an object. In C++, this is relatively unusual -- most of the time, you want to just define a local object so creation and destruction will be handled automatically.


// by the way, is this the right way to do this?

What you are doing is correct. The best approach depends on how you want to use that vector.

But I find it a little too much for my code. I wonder, is there any more, brief way to ask for an iterator regardless of the type?

Yes, you can define the vector as a type:

typedef std::vector<a_complicated_whatever_identifier *> MyVector;
MyVector * vectPtr = new MyVector;
MyVector::iterator iter;


If you have a recent compiler, I suggest giving c++11 a spin. Most compilers support it in the form of the --std=c++0x flag. You can do all kinds of nifty things related to type inference:

std::list<std::map<std::string, some_complex_type> > tables;

for (auto& table: tables)
{
     std::cout << table.size() << std::endl;
}

for (auto it = tables.begin(); it!= tables.end(); ++it)
{
     std::cout << it->size() << std::endl;
}

Also look at decltype and many other handyness:

// full copy is easy
auto clone = tables; 

// but you wanted same type, no data?
decltype(tables) empty;

Contrived example of combining typedefs with the above:

typedef decltype(tables) stables_t;
typedef stables_t::value_type::const_iterator ci_t;
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号