STL set and its iterator.

P

Prawit Chaivong

Hi, gurus

Is it safe to do this in function?
'return &(*iterator)';
And iterator is std::set<something>::iterator

Regards,
 
P

Peter Julian

Prawit Chaivong said:
Hi, gurus

Is it safe to do this in function?
'return &(*iterator)';
And iterator is std::set<something>::iterator

You've got a char literal '...' and its not being assigned to anything. If
you remove the single-quotes in the statement above:

return &(*iterator);

Then no-one can answer your question since its unknown whether the address
of the derefenced object (or pointer) is local to the function.
 
P

Prawit Chaivong

Peter said:
You've got a char literal '...' and its not being assigned to anything. If
you remove the single-quotes in the statement above:

return &(*iterator);

Then no-one can answer your question since its unknown whether the address
of the derefenced object (or pointer) is local to the function.

OK, It was my fault.
This is an example.

------------------------------------
std::set<MyClass> g_set;

void getBegin(MyClass **s)
{
std::set<MyClass>::iterator itr;
itr = g_set.begin();
*s = &(*itr); // is '*itr' temporary?
}
-------------------------------------
 
A

Andre Kostur

OK, It was my fault.
This is an example.

------------------------------------
std::set<MyClass> g_set;

void getBegin(MyClass **s)
{
std::set<MyClass>::iterator itr;
itr = g_set.begin();
*s = &(*itr); // is '*itr' temporary?
}
-------------------------------------

IIRC: by definition *itr is a reference to the instance of the object in
the set. You then take the address of it. This pointer should be valid
until that element in the set is destroyed.
 
P

Phil Staite

And if g_set is empty... ???

;-)

That's the fundamental problem with interfaces that return
pointers/references... What do you do when you have nothing to point or
refer to?
 
P

Peter Julian

This is an example.

------------------------------------
std::set<MyClass> g_set;

void getBegin(MyClass **s)
{
std::set<MyClass>::iterator itr;
itr = g_set.begin();
*s = &(*itr); // is '*itr' temporary?
}
-------------------------------------

You are way too short on information and your knowledge on references, set
containers + iterators is rather lacking. This is making helping you very,
very difficult.

An iterator's type should always be type defined, since each STL container
supports predefined iterator types. The question you are asking refers to
*itr and whether its a temporary. When written correctly, and by using a
reference to the std::set container as a parameter to the function, *itr
returns the object thats first in the set's order of elements.

MyClass getBegin(set<MyClass>& ref_set)
{
typedef std::set<MyClass>::iterator SITER;
SITER it = ref_set.begin();
return *it;
}

A std::set container relys on a predicate
(http://en.wikipedia.org/wiki/Predicate).
When you insert an object into such a container, that container needs to
compare the insertable element to the elements already in the set. The
following will fail unless you supply an appropriate less_than operator
function to compare MyClass-type objects.

MyClass a;
MyClass b;
MyClass smallest = a < b ? a : b; // returns the lesser of the 2

By default, the std::set uses less<> to insert elements in the ordered
container. This means your MyClass class needs to have access to an
operator< for the std::set container to be able to order the elements when
inserting. Usually, the operator< is not a member of the class:

bool operator<(const MyClass& left, const MyClass& right)
{
....
}

In the case you wish to compare MyClass's private members to each other, you
need to make that operator a friend of the class.

#include <iostream>
#include <set>

class MyClass
{
int m_n;
public:
MyClass(int n) : m_n(n) { }
~MyClass() { }
int getN() { return m_n; }
// friendify op< to allow access to private members
friend bool operator<(const MyClass& left, const MyClass& right);
};

// global operator< to compare MyClass-type objects
bool operator<(const MyClass& left, const MyClass& right)
{
return left.m_n < right.m_n;
}

MyClass getBegin(std::set<MyClass>& ref_set)
{
typedef std::set<MyClass>::iterator SITER;
SITER it = ref_set.begin();
return *it;
}

int main()
{
std::set<MyClass> myset;
for (size_t i = 1; i < 10; ++i)
{
myset.insert(i); // automatically ordered
}

// using a non-member function:
MyClass first = getBegin(myset);

std::cout << "[using getBegin()]\tfirst element's value in set = ";
std::cout << first.getN();

// alternative to using a non-member function
typedef std::set<MyClass>::iterator SITER;
SITER it = myset.begin();

std::cout << "\n[using iterator]\tfirst element's value in set = ";
std::cout << (*it).getN();

return 0;
}

/* output:

[using getBegin()] first element in set = 1
[using iterator] first element in set = 1

*/
 
P

Peter Koch Larsen

Prawit Chaivong said:
OK, It was my fault.
This is an example.

------------------------------------
std::set<MyClass> g_set;

void getBegin(MyClass **s)
{
std::set<MyClass>::iterator itr;
itr = g_set.begin();
*s = &(*itr); // is '*itr' temporary?
}
Apart from what others have mentioned, you seem to forget that *iter returns
a MyClass const&, not a MyClass&

/Peter
 
P

Peter Julian

Peter Koch Larsen said:
Apart from what others have mentioned, you seem to forget that *iter returns
a MyClass const&, not a MyClass&

Thats a good point since modifying the referred_to_object could potentially
break that container's sequence.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,296
Messages
2,571,535
Members
48,281
Latest member
DaneLxa72

Latest Threads

Top