C#
  Home arrow C# arrow Page 4 - SatView: Pointer Perfect, part 4
ASP Free Forums 
.NET  
ASP  
ASP Code  
ASP.NET  
ASP.NET Code  
BrainDump  
C#  
Code Examples  
Database  
Database Code  
IIS  
Microsoft Access  
MS SQL Server  
Visual Basic.NET  
Windows Scripting  
Windows Security  
XML  
ASP Web Hosting  
ASP.NET Web Hosting 
Mobile Linux 
App Generation ROI 
Windows Web Hosting
 
IBM® developerWorks 
Sun Developer Network 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
C#

SatView: Pointer Perfect, part 4
By: J. Nakamura
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 2 stars2 stars2 stars2 stars2 stars / 6
    2004-12-27

    Table of Contents:
  • SatView: Pointer Perfect, part 4
  • Fence Post Errors
  • Dangling Pointers
  • Performance Hit When Initializng
  • Object Slicing

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    SatView: Pointer Perfect, part 4 - Performance Hit When Initializng


    (Page 4 of 5 )

    Something you might easily overlook is that declaring an array of objects invokes the constructor for each object in that array. When this object takes some time to create, declaring an array of these objects might claim a hit on the performance of your application.

    When you are not sure whether you will need all 1000 objects in the array, it might be wiser to reserve 1000 pointers instead of the objects themselves. Of course don’t forget to initialize all the pointers to NULL and to create/delete them as you need.

    Programmers aware of this behavior are sometimes still caught by surprise when using the std::vector. The vector is very handy to use instead of built-in arrays, because it can be treated like a built-in array (this is in fact one of its requirements) and can grow dynamically as well. Don’t let this mislead you into thinking that you will only be creating as many objects as you want to put into it when you are not taking the necessary precautions.

    It is in fact cheaper to construct a built-in array of 10 objects than to use a plain std::vector when you will only need 5 of the objects! Let me demonstrate.

    class MyClass {
    public:
      MyClass() { (void)printf(“>> MyClass constructed <<\n”); }
      MyClass(MyClass const &other)
     { (void)printf(“** MyClass copy constructed **”); }
    MyClass& operator=(MyClass const &other)
     { (void)printf(“** MyClass re-assigned **\n”); return *this; }
    ~MyClass() { (void)printf(“>> MyClass destructed <<\n”); }
    };

    void test()
    {
    MyClass myClass;
    (void)printf(“creating an array[5].\n”);
    MyClass arry[5];
    int idx;
    for (idx=0; idx<5; ++idx)
    {
      (void)printf(“add #%d.\n”, idx);
      arry[idx] = myClass;
    }
    (void)printf(“done.\n\n”);

    (void)printf(“creating a plain vector.\n”);
    std::vector<MyClass> vect;
    for (idx=0; idx<5; ++idx)
    {
      (void)printf(“add #%d.\n”, idx);
      vect.push_back(myClass);
    }
    (void)printf(“DONE.\n\n”);

    (void)printf(“creating a vector… ”);
    std::vector<MyClass> vect2;
    (void)printf(“and reserving space for 5.\n”);
    vect2.reserve(5);
    for (idx=0; idx<5; ++idx)
    {
      (void)printf(“add #%d.\n”, idx);
      vect2.push_back(myClass);
    }
    (void)printf(“DONE.\n\n”);
    }

    Let's take a look at what the first part, creating an array[5], generates for output:

    creating an array[5].

    >> MyClass constructed <<
    >> MyClass constructed <<
    >> MyClass constructed <<
    >> MyClass constructed <<
    >> MyClass constructed <<
    add #0.
    ** MyClass re-assigned **
    add #1.
    ** MyClass re-assigned **
    add #2.
    ** MyClass re-assigned **
    add #3.
    ** MyClass re-assigned **
    add #4.
    ** MyClass re-assigned **
    DONE

    Nothing surprising here…exactly what we expected: MyClass was constructed 5 times, just by declaring an array[5] of it. Then myClass was copied into 5 objects in that array by using the assignment operator. Now take a look at the output of the second part; the plain vector getting MyClass pushed into it 5 times:

    creating a plain vector.

    >> MyClass constructed <<
    add #0.
    ** MyClass copy constructed **
    ** MyClass copy constructed **
    >> MyClass destructed <<
    add #1.
    ** MyClass copy constructed **
    ** MyClass copy constructed **
    ** MyClass copy constructed **
    >> MyClass destructed <<
    >> MyClass destructed <<
    add #2.
    ** MyClass copy constructed **
    ** MyClass copy constructed **
    ** MyClass copy constructed **
    ** MyClass copy constructed **
    >> MyClass destructed <<
    >> MyClass destructed <<
    >> MyClass destructed <<
    add #3.
    ** MyClass copy constructed **
    ** MyClass copy constructed **
    ** MyClass copy constructed **
    ** MyClass copy constructed **
    ** MyClass copy constructed **
    >> MyClass destructed <<
    >> MyClass destructed <<
    >> MyClass destructed <<
    >> MyClass destructed <<
    add #4.
    ** MyClass copy constructed **
    ** MyClass copy constructed **
    ** MyClass copy constructed **
    ** MyClass copy constructed **
    ** MyClass copy constructed **
    ** MyClass copy constructed **
    >> MyClass destructed <<
    >> MyClass destructed <<
    >> MyClass destructed <<
    >> MyClass destructed <<
    >> MyClass destructed <<
    DONE.

    What is going on here you might wonder? It is quite easy to explain: std::vector reallocates enough memory to hold its current number of objects plus one extra, every time we push another myClass into it. The first “copy constructed” message and the last “MyClass destructed” message are for a temporary object holding a copy of myClass.

    The other messages are for copy constructing the current objects into the reallocated memory plus one for the object we are pushing into the vector. The destruction messages are for the objects being freed from the current allocated memory since they are not needed anymore.

    It is pretty clear that using a built-in array of 10 objects is much cheaper than the way we are using the vector in the sample above! The third part shows proper usage of the std::vector.

    creating a vector... and reserving space for 5.
    add #0.
    ** MyClass copy constructed **
    add #1.
    ** MyClass copy constructed **
    add #2.
    ** MyClass copy constructed **
    add #3.
    ** MyClass copy constructed **
    add #4.
    ** MyClass copy constructed **
    DONE.

    This is exactly the type of behavior we want to see from the std::vector! It goes without saying that you need to understand what you are doing and how libraries (like the STL) behave when you are using them.

    Always measure your code before assuming where performance bottlenecks might reside. In the case of large arrays of expensive objects being the problem, resolving to pointers might solve your problem.

    More C# Articles
    More By J. Nakamura


     

    C# ARTICLES

    - C# and XML
    - Pointers and Arrays in C#
    - C# 3.0 Extension Methods
    - Overloading Operators in C#
    - Iterators and Nullable Types
    - Patterns and Iterators in C#
    - C# Exceptions
    - Methods in C#
    - Delegates and Events in C#
    - Advanced C#
    - Working with Regular Expressions in C#
    - Sending Simple E-Mail in C#
    - Building C# Comparable Objects: IComparable ...
    - Color Transformation Applications in C# GDI+...
    - Performing Color Transformation Operations i...





    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 1 hosted by Hostway
    Stay green...Green IT