• Advertisement
Sign in to follow this  

2 questions related to speed and efficiency

This topic is 4586 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

q#1) - what kind of overhead is brought about when using static casts... is it a slow process, or can it pretty much be used freely? q#2) - Ive heard negatives about the stl vector being slow... what would be a better solution with the same type of functionality? ??? ;P ???

Share this post


Link to post
Share on other sites
Advertisement
1) It depends purely on the cast. Casting from an unsigned int to an int will involve absolutely zero runtime overhead. Casting from float to int is more likely to generate slight overhead. But this is rarely the cause of slow code, so don't worry about it.

2) The std::vector is not necessarily the fastest possible implementation. But it is almost certainly better (faster) than anything you can write yourself. Combined with a custom allocator (loki and boost pooled allocators are common), it's very difficult to beat the STL vector, except in very specific usage scenarios.

Share this post


Link to post
Share on other sites
It depends on the usage of vector. If you are adding/removing stuff to the end of the vector (push_back) then it is extremely fast, because that is what vector is used for. any other insertion requires linear time. for more information about STL check out this website:
http://cplus.about.com/od/stl/

I have found it very useful as I am still new to STL myself.


~guyaton

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
STL vector can be slow for 2 reasons:
1) You do lots of allocations that cause the storage buffer to be resized a lot. This can generally be mitigated by calling reserve() with a reasonable value.

2) You do lots of deletes. There is no way to combat the slow-down in this case because the nature of the operation involves a crap-load of memory copying. If this is your problem you should swith to std::deque. Deque is a super-cool data structure that provides all the functionality of vector, but offers much faster deletes. The cost is that you get a very minimal slow-down when accessing a random element in the structure. I've had great luck with std::deque in the past.

--ajas

Share this post


Link to post
Share on other sites
thanks for that...

but a little more on the first question..

this i kinda what i am doing..

i have a base class of substantial size...
in this class store the type of derived class it is through an enum
"m_baseType = DERIVED1;"

my derived classes add on to the base and sets the appropiate enum value for their type..
"m_baseType = DERIVED7;"

in a vecotor i store pointers to the derived classes as though they were the base class..
"vector<base*> myStuff;"

then when i need to use the class in the vector i check its enum then static cast it to the proper derived class..

switch (myStuff.at(2)->m_baseType)
{
case: DERIVED1
static_cast<DERIVED1*>(myStuff.at(2));
break;

case: DERIVED7
static_cast<DERIVED7*>(myStuff.at(2))
break;

}
// this could be in a function that would return the cast type..



is that good practice? or a no no?

Share this post


Link to post
Share on other sites
Generally speaking (although as with many things, this is by no means absolute) if you have to downcast, your inheritance hierarchy is probably somewhat non-optimal.

One of the main points of inheritance is polymorphism, i.e. that objects sharing a common interface may behave differently depending on underlying type. In order to extend a class publicly, the subclass should wish to share the base class' public interface and provide different but relevant implementations for virtual functions.

Basically, if objects are related by public inheritance and are used by reference to the base class, there should be a common interface by which they can be manipulated and varying behaviour should be implemented using virtual functions rather than switch statements.

Hope that helps.

Share this post


Link to post
Share on other sites
Yeah that's an OOP no-no.

What exactly are you doing that requires you to know the derived class? You should replace whatever that is with a function that your derived classes override.

So for example, say you're finding the derived class so that you can print the thing out as a string. What you *should* do is have an abstract toString() on the base class, define a toString() for every derived class, and call toString() on your copy of the base-class.

Having derived classes works best when the outsider class neither knows nor cares which derived class he is using. All he knows is that whatever class he has, it's going to fulfill the responsibilities of the base class, and it knows how to take care of itself.

Share this post


Link to post
Share on other sites
for those who like demonstrations:


#include <string>

using namespace std;

class CBase
{
public:
virtual toString() {};

string m_str;
};

class CDerived
{
public:
virtual toString() { this->m_str.cstr(); }
};

CBase *derived = new CDerived();

if( strcmp( "somestring", derived->toString() ) == 0 )
{
//something
}




Quote:

Having derived classes works best when the outsider class neither knows nor cares which derived class he is using. All he knows is that whatever class he has, it's going to fulfill the responsibilities of the base class, and it knows how to take care of itself.


the function doesn't care what the base class is, just calls the derived classes function.

Share this post


Link to post
Share on other sites
okay yeah that makes sense... i did not know that you were supposed to put virtual on the base and derived class function...

thanks for it ;P

Share this post


Link to post
Share on other sites
You don't need to put virtual on the derived class's function unless you want the derived class to be extended and overriden itself.

Share this post


Link to post
Share on other sites
You can do lots of really cheap deletes with an std::vector by swapping the item you want to delete with the last element in the vector and then pop_back(), assuming you don't need the vector to be sorted. No memory copying/moving would be necessary in this case, other than swapping the elements.

Share this post


Link to post
Share on other sites
I put the virtual in the Derived classes function in case another class inherited CDerived (just in case). It is not required to be in the derived classes function declaration. sorry for the confusion

~guyaton

Share this post


Link to post
Share on other sites
ok another question


base
derived1
derived1Dirived1


^^^^^^ all are classes

base has virtual init()

derived1 does not use init()
but
derived1Dirived1 does use init()
will derived1 need to still declare inti()


also... when using a..

std::vector<base*> vBase;
vBase.push_back(new derived1);

when i call...

vBase.at(0)->init();

who's init() will it call..?

thanks.. for the assistance

Share this post


Link to post
Share on other sites
Quote:
Original post by MTclip
ok another question


base
derived1
derived1Dirived1


^^^^^^ all are classes

base has virtual init()

derived1 does not use init()
but
derived1Dirived1 does use init()
will derived1 need to still declare inti()


Just what you need to do here depends what you mean by "does not use", and whether the base init() is "pure" virtual.

Quote:

also... when using a..

std::vector<base*> vBase;
vBase.push_back(new derived1);

when i call...

vBase.at(0)->init();

who's init() will it call..?

thanks.. for the assistance


The derived1::init(). This is the whole point; because the function is virtual, an invocation on a pointed-to (or referred-to) object will use the actual object's code - i.e. it will "behave polymorphically". The compiler automatically generates code and data needed to "look the function up in a vtable", which replaces the explicit code you would otherwise have to write to check the type. Implicit is good: it's better organized, and less work for you. :)

Note that you could not do this with a vector of base objects (rather than pointers): the vector would only have enough storage space for base objects, so base objects would be what gets copied in, and the "rest of" any inserted object would be discarded by the copy ([google] "object slicing").

Requiring this polymorphic behaviour is one of the few good reasons to store a container (e.g. vector) of pointers rather than of actual objects (in "ordinary" cases, the overhead is useless and just adds extra complexity). Note however that you still have a memory management problem to deal with: since now the vector has a pointer to the object as well as whatever pointer was your "handle" when you inserted it, you must decide who "owns" the object - since anything you new must be delete'd exactly once.

Share this post


Link to post
Share on other sites
1) I really wouldn't worry about it. Just concentrate on your inner-most loops. I'd keep my data formatted with the corect cast so my inner-most loops can digest it easily, avoiding any such problems.

2) Again, it's all about inner-most loops. If you're storing data in a vector so that it can later be passed to your most CPU intensive code, it's not a big deal. However, I wouldn't be crunching a vector in a function that's called 100,000 times per second.

Use what you have at your disposal to easily structure your application. Unless you're really having speed issues, don't worry about it. Write now, optimize later.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement