Solved

Find an object in a multiset

Posted on 2009-05-15
12
396 Views
Last Modified: 2013-12-14
Hi,
I am trying to find within a container whether or not an object of certain attributes exists.
I thought i could use the count member function of the multiset container but it is not working.

I need to only match by the second and third parameters in the actor objects that are stored in the all_actors container. Within the actors class, I have overloaded the comparitor '==' to reflect that these are the 2 parameters that justify the objects to be the same as one another.

friend bool operator == (const actor& a1, const actor& a2)      
            {
                  return((a1.position==a2.position) && (a1.type==a2.type))?true:false;                  // Overload the comparator operator
            }
Shouldnt the member function know that with my overloaded operator in the actor class - that I want to compare second and third parameter? Surely i dont need to match ALL the attributes for the count member function to count it?

Many thanks


bool find_curr_actor(string str1, string str2, string str3)			// Function to find the current actor object and point the member iterator 

																			// to this actor object.

	{

		actor *search_actor;												// Create a temporary pointer to actor with which to perform the search.

		search_actor= new actor(0,str1,str2,str3);							// Assign a new actor with the search properties and a reference ID of 0.

		int count=all_actors.count(*search_actor);

		if (count==0)														// If the actor wasnt found in the set then say so

		{

			cout<<endl<<"Actor Position "<< search_actor->getposition()

				<<" and Type:"<<search_actor->gettype()<<"  not found";

			delete search_actor;											// Delete the search object

			return false;

		}

		else

			return true;

	}

Open in new window

0
Comment
Question by:simondopickup
  • 5
  • 4
  • 2
  • +1
12 Comments
 
LVL 16

Accepted Solution

by:
HooKooDooKu earned 400 total points
ID: 24395189
I assume that inside the all_actors.count() function is where you are attempting to use the overloaded == operator.  If so, then some source code on that function would be helpful.

As a side comment, the code...
int count = all_actors.count(*search_actor);
...looks strange on a couple of levels.

First of all search_actor is a pointer.  Many people start the names of variables that contain pointers with a 'p' to help keep up with variables that are actual values/objects and those that are just pointers to values/objects.  So you might want to try somethings like naming the variable something like pSearchActor.

Second, unless the count() takes an 'actor' object BYREF like this...
int count( actor& )
...then you are passing the actor object BY VALUE which means you are using many more resources than is needed.

And similar to the notion to naming pointer variables starting with p is to name classes starting with C.  For one, it makes it obvious in the code that a new class object is being created, and you can reuse the simple name as a variable name.
So the code where you create a new actor variable would look something like this...
CActor* pActor = new CActor(...)
... and the count subroutine could look something like this...
int CActorCollection::count( CActor& Actor )
{
    int Result = 0;
    for( int i=0; i < m_Count; i++ )
    {
        if( Actor == m_Collection.GetActor( i ) )
        {
            Result++;
        }
    }
    return Result;
}
0
 

Author Comment

by:simondopickup
ID: 24395471
Thanks for the advice. I will start using that notation i think - keeping up with all my variables is a nightmare at present.

I have sorted my prblem out. I dont think there is a member function of the multiset container to count instances of an object that match an input such as search_actor. So i have just manually iterated through the container and this seems to work.

Oh - and if i use the pointer to an object as an argument to count then isnt that passig it passing it by reference?
0
 
LVL 16

Expert Comment

by:HooKooDooKu
ID: 24396187
In the days of C, there was only one way to pass a variable to a subroutine... By Value.  That ment that when you passed a variable to a function, the only thing that got passed was a COPY of the current value of the variable.

Now the way C allowed you to FAKE passing a variable By Reference was to pass a pointer to the variable.  Now a pointer is just a memory address.  And a memory address, or a copy of the memory address is still the memory address.  Once you had the address of a variable, then you could access that variable for reading or writing.  You just had to use the '*' operator to dereference the memory address.

C++ introduced TRUE passing a variable By Reference.  Now under the hood, C++ is really just passing a memory address.  But the difference is that C++ does all the dereferencing for you.

As an example the two functions in the Code Snippet do exactly the same thing.  In one case you pass a pointer to a variable, in the other you pass the variable By Reference.  There is no difference in what actually happens, the difference is stricktly in the syntax that you use.

For comparision, I've also added a pass By Value example.  As written, this function accomplishes absolutely nothing.  When the function is called, a copy of the values for First and Second are sent to the function.  The function then updates the value of theses COPIES, leaving the original variables unchanged.  Sure the copies get updated in the subroutine, but given that the subroutine doesn't do anything with these copied values, as soon as the function call is over, these copies are destroyed and the original variables still contain their original value.
//Functions that takes two integer values, adds 1 to the 1st and adds 2 to the second
 

void AddOneTwo( int* pFirst, int* pSecond )

{

    (*pFirst)++;

    (*pSecond) = (*pSecond) + 2;

}

void AddOneTwo( int& First, int& Second )

{

    First++;

    Second = Second + 2;

}
 

//Pass By Value example... net result is nothing is accomplished

//But notice that the syntax is the same as the By Reference

// except for how the parameters were declared

void AddOneTwo( int First, int Second )

{

    First++;

    Second = Second + 2;

}

Open in new window

0
 
LVL 16

Expert Comment

by:HooKooDooKu
ID: 24396289
Additionally, the syntax...
int count=all_actors.count(*search_actor);
... is NOT passing a pointer to a fucntion call.  The '*' operator is dereferencing the pointer variable.  Basically, you can think of the * operator as meaning "go get the value of what is at the following memory address".  That means the following two examples are equivilent.  The only real difference is where the object search_actor is created and it's life time.  In the case of the pointer, new will allocate space for the object on the heap, and it will live there until the object is destroyed with delete.  In the case of the variable without a pointer, the object gets created on the local stack, and the object automatically gets destroyed when the function it was declared in is complete.
//First method with pointers

actor *search_actor;				

search_actor= new actor(0,str1,str2,str3);			

int count=all_actors.count(*search_actor);
 

//Second method with objects

actor search_actor(0, str1, str2, str3);

int count=all_actors.count(search_actor);

Open in new window

0
 

Author Comment

by:simondopickup
ID: 24396372
Thanks, that has cleared up some vital black holes in my knowledge!

Just one more question if you dont mind - i will award you the points.

I am - at the minute creating loads of objects of class instances. However, having parsed all my log files and created the objects, it is clear that my objects have only been allocated to the stack - thus at the end of my parse - I have nothiing stored!!!
I have been reading about scope (namely going out of it) - and i wondered what you thought about my problem. I really want my objects to be stored somehow more permanently so that i can query them later on from the memory. I dont want to push all the objects onto a database just yet!!!

Any thoughts or advice?>

Simondo :)
0
 
LVL 16

Expert Comment

by:HooKooDooKu
ID: 24397854
When ever you create an object with the keyword 'new', you are creating them on the 'heap' where they will live for the entire program... and will create a memory leak if you should forget to destroy them with 'delete'.

When ever you create an object without the keyword 'new' in a function... like this...
CMyObject obj( parm1, parm2 );
... then the CMyObject by the name obj lives for the duration of the function for which it is defined... and perhaps even shorter than that, for if it's declared inside a block (like within a for loop) it only lives during that block.

For example, in the following code snippet, the object 'obj' lives for the entire function, while obj2 only lives inside the for loop, while obj3 creates a memory leak.

Additionally, to understand some of this, you might want to create a test project with some test classes.  What you should do is in the constructor and destructor of the objects, display a message box.  Then create some code and see when the constructors and destructors are called.

void Test()

{

  CMyObject obj(1);

  CMyObject* pObj3 = new CMyObject(3);

  ... do stuff ...

  for( int i=0; i < obj.GetCount(); i++ )

  {

      CMyObject obj2(2);

      ... do stuff ...

  }

  //At this moment the obj2 destructor is called
 

  return;

  delete pObj3; //Memory leak because this comes AFTER the above return

                //pObj3 will live forever 

}//<--At this moment, the obj destructor is called

 //if the think of the return statement jumping to the functions closing brack

Open in new window

0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 

Author Comment

by:simondopickup
ID: 24398997
So for objects not defined as new, is there a way to store them on the heap? Declare them in some static manner??
0
 
LVL 16

Expert Comment

by:HooKooDooKu
ID: 24399995
If an object is declared as static, then it would be created on the heap and would exist for the lifetime of the application.

Example:

void Test()
{
    static CMyObject obj(1);
    ... Do Stuff ...
}

The moment your application starts, the constructor for obj inside the Test() function would be executed.  When you finally call the Test() function, the line with the keyword 'static' is essensially skipped because the object has already been created and will live for the life time of the application.  However, the only place you can access it is within the function Test() {unless you get a pointer to it and start passing pointers all over the place}.

But a word of warning... in a typical C++ application, the key word static should be used SPARINGLY.  If you are trying to define lots of variables or objects using static, then you likely do not have a good design for your application.  Instead, if you want objects to have a long life on the heap (rather than just during a function call on the stack) then you really need to setup a pointer and create the object with 'new'.
0
 
LVL 39

Assisted Solution

by:itsmeandnobodyelse
itsmeandnobodyelse earned 100 total points
ID: 24400426
>>>> I am trying to find within a container whether or not an object of certain attributes exists.
I didn't achieve to follow all deepness of discussion here in that thread but coming back to your initial question, you best would use the appropriate container and it is one single call to find out what you want:

bool application::findActor(actor_id act_id, actor & act)
{
   map<actor_id, actor>::iterator it = all_actors.find(act_id);
   if (it == all_actors.end()) return false;
   act = it->second;
   return true;
}  

The above would require a structure defining the actor's id like

struct actor_id
{
    int position;
    int type;
    friend bool operator<(const actor_id& aid1, const actor_id& aid2)
    {
         return (aid1.position < aid2.position ||
                     (aid1.position == aid2.position) && aid1.type < aid2.type));
    }
};
0
 
LVL 1

Expert Comment

by:maartennieber
ID: 24401661
HooKooDooKu gives a lot a valuable advise, but as far as I know, starting classes with a capital C is not standard, so I would not make that into a habit.
An example style guideline on type names from Google:

http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml?showone=Type_Names#Type_Names

0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 24401789
>>>> starting classes with a capital C is not standard, so I would not make that into a habit
It was standard in MFC. But I always avoided to apply that for my private classes not least because of making the difference clear.
0
 

Author Comment

by:simondopickup
ID: 24412328
Yes, but if i start to create dynamic storage durations for my objects in the containers - will i still be able to access them globally?
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now