Thread: Reinventing the Wheel

  1. #16
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> I just don't like relying too much on other people's code.
    That may work in some specific cases, but there are tons of reasons to rely on existing libraries over creating your own.

    This is especially true of the standard library (part of which in C++ is referred to as the STL). The interface is standardized, so you can be reasonably sure your code will work for a long time on any platform. This also means that most other developers familiar with the language can understand what the code is doing because the library is part of the language. For your own library, it is almost assured that a developer new to the code will have to learn your API from scratch.

    The standard library implementations are thoroughly tested because so many people use them. This contrasts with your own library that gets far less testing and will almost always have far more bugs. In some cases you can optimize library functionality for specific tasks you need, but the standard library implementations have all been highly optimized as well, and in many cases this will still be better than your own.

    It seems to be a natural tendency to want to write your own solution rather than search for an existing one, but in the end the effort is much greater and the reward is smaller if you do. This is true even for non-standard libraries. In some cases you will find that there are no widely available and tested libraries for a specific task, and in those cases writing your own makes sense.

    Your line probably stops at the C standard library. If you are programming in C++, though, that line should at least extend to the C++ standard library, and probably a lot further.

  2. #17
    Registered User samGwilliam's Avatar
    Join Date
    Feb 2002
    Location
    Newport
    Posts
    382
    Just had a quick look at some STL docs.

    Vectors? WTF's wrong with an array? I mean, seriously, it's built into the language. Oh, it says it 'eliminates the chore of dynamic memory allocation'.

    I've never had a problem with new and delete - they take about 4 seconds to type. Hardly a 'chore'.

    I imagine there's a string one too, when strings are already about as simple as it gets.

    Ironic, really, as this seems like the textbook definition of reinventing the wheel for the sake of it.

  3. #18
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    That same attitude can be applied to strcpy. How hard is it to write a loop? That's about 8 seconds. But that is also part of the standard library because it is a commonly used task, it is encapsulated in a function so there is no chance for the user to make a mistake and cause a bug by doing it themselves, and it can be optimized by the library implementors to do better than a simple loop.

    Have you ever had memory leaks? Have you ever had an error where you deleted something twice? Have you ever tried to resize a dynamic array? Finding and fixing memory leaks is a chore. Finding memory related bugs in general is a chore. Resizing a dynamic array is a chore. The vector class eliminates those chores.

    Why would you ever need a nail gun when a hammer will do just fine? Perhaps if you're building a house and hammering in thousands of nails, you'll think differently.

    If you prefer C, that's fine, but I think your attitude about C++ is coming from a lack of experience with it.

  4. #19
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I've never had a problem with new and delete - they take about 4 seconds to type. Hardly a 'chore'.
    Typing new and delete (or rather, new[] and delete[]) is not the problem. The problem is having to rewrite the memory management logic for dynamic arrays, and making sure that it is both efficient and correct. For example, you have to ensure that delete[] is properly called. This might be done by using the destructor, but it also means that you have to write it in for every class that uses a dynamic array. Vectors and other standard containers take the memory management chore away by providing well tested and optimised libraries. Instead of having to call delete[] in your own destructor, the container's destructor handles it for you.

    Ironic, really, as this seems like the textbook definition of reinventing the wheel for the sake of it.
    Hardly. You probably reinvent the wheel far more often.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #20
    Registered User samGwilliam's Avatar
    Join Date
    Feb 2002
    Location
    Newport
    Posts
    382
    I suppose you have to draw the line somewhere. But arrays are built in. It'd be like writing your own add () function, instead of using the + operator (or something). And a string is just an array anyway, so that's equally as futile IMO.

    Don't get me wrong, I can see the point of stuff like linked lists but why replace strings and arrays?

    And I do tend to pick and choose what elements of C++ I use, but I'm perfectly comfortable with that.

  6. #21
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    But arrays are built in. It'd be like writing your own add () function, instead of using the + operator (or something). And a string is just an array anyway, so that's equally as futile IMO.

    Don't get me wrong, I can see the point of stuff like linked lists but why replace strings and arrays?
    Hear from the man himself: How do I deal with memory leaks?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #22
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Strings in C are "as simple as it gets"? You have some very low expectations.

    Arrays are built in? Yeah, but dynamic arrays? Nope, they aren't.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  8. #23
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> why replace arrays?
    The vector is not a replacement for arrays, it is a replacement for dynamic arrays.

    >> why replace strings?
    Let's say you are creating a string that holds a bunch of formatted data that you plan to either write out to a file or use directly from the string. You build that string from the data in your app by adding to it (e.g. in a csv or xml format). You don't know how much data there will be, there could be only a little, there could be a lot.

    How do you handle that with a C style string? You'd have to use dynamic memory allocation since the string could be huge. But you don't want to over allocate in case there isn't much data to handle. So you allocate something small to start off, and use strcat to append to the string as you go. But then what if the array fills up, you have to create a new array with a larger size and copy the contents from the old array to the new one, then continue concatenating. Just writing this code is a chore, let alone getting it right.

    For the string class it would be as simple as:
    Code:
    std::string my_string;
    while (more_data())
    {
      my_string += get_data();
    }
    All that other stuff is handled automatically.

  9. #24
    Registered User samGwilliam's Avatar
    Join Date
    Feb 2002
    Location
    Newport
    Posts
    382
    I'd use a linked list in that case.

    Of course, I'd code it myself, too...

  10. #25
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    A linked list of chars?

  11. #26
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    A linked list for a string? You mean per character? Or per buffer chunk? And how do you then handle the thing? Using a bunch of specialized functions? Do you separate them into their own module?

    Congratulations, you've just reinvented the wheel.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  12. #27
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by samGwilliam View Post
    I'd use a linked list in that case.

    Of course, I'd code it myself, too...
    Excellent idea. Now instead of using 1 byte per character, you use several times as much. Four bytes or so for the link pointer. One byte for the character itself. And potentially eight or more bytes for memory allocator bookkeeping for each allocated node.

    Congrats, your method of increasing memory usage by a factor of 13x has truly impressed me.

  13. #28
    semi-colon generator ChaosEngine's Avatar
    Join Date
    Sep 2005
    Location
    Chch, NZ
    Posts
    597
    Quote Originally Posted by samGwilliam View Post
    Vectors? WTF's wrong with an array? I mean, seriously, it's built into the language. Oh, it says it 'eliminates the chore of dynamic memory allocation'.

    I've never had a problem with new and delete - they take about 4 seconds to type. Hardly a 'chore'.
    Really? let's have a look at a piece of code then.
    Code:
    void SomeFunc(void)
    {
        int *x = new int[100];
    
        SomeOtherFunc(x);
    
    
        delete[] x;
    }
    we've allocated some memory, called a function, deleted our memory like a responsible programmer and all is happy in the valleys, right?

    but let's have a look at SomeOtherFunc()
    Code:
    struct big
    {
        double d[100000];
    }
    
    void SomeOtherFunc(int *p)
    {
        for (int i = 0; i < 200; i++)
        {
             p[i] = i;
        }
    
        big *reallyBig = new big[100000];
    
        // some code
    
        delete[] big;    
    }
    ok this code has 2 problem (apart from not doing anything useful). The first is that we've overwritten the bounds of our array. Not such a big deal, we should've passed in the size of the array, but it wouldn't necessary with a vector (which knows it's size).

    The second is a bit trickier. You see, there's a very good chance that we don't have enough memory to allocate reallyBig. On a standards-compliant compiler, that means an std::bad_alloc exception will be thrown. Now we're in really big trouble since x will not be deleted.

    ok, but we can catch the exception! so let's rewrite SomeFunc
    Code:
    void SomeFunc(void)
    {
        int *x;
        try
        {
             x = new int[100];
    
             SomeOtherFunc(x);
    
             delete[] x;
         }
         catch (std::bad_alloc &)
         {
             delete[] x;
         }
    }
    ahh, much better. except, we've swallowed the exception so the caller of SomeFunc doesn't know it failed. No problem, let's rethrow the exception.

    Code:
    void SomeFunc(void)
    {
        int *x;
        try
        {
             x = new int[100];
    
             SomeOtherFunc(x);
    
             delete[] x;
         }
         catch (std::bad_alloc &)
         {
             delete[] x;
             throw;
         }
    }
    phew! dodged that bullet. except now another coder has changed SomeOtherFunc()!

    Code:
    struct big
    {
        double d[100000];
    }
    
    void SomeOtherFunc(int *p)
    {
        for (int i = 0; i < 200; i++)
        {
             p[i] = i;
        }
    
        big *reallyBig = new big[100000];
    
        if (!ConnectToInternet())
        {
             throw Unconnected();
        }
    
        delete[] big;    
    }
    ahh crap, now we have to add another catch clause. That sucks. To hell with that, let's just catch all exceptions.
    Code:
    void SomeFunc(void)
    {
        int *x;
        try
        {
             x = new int[100];
    
             SomeOtherFunc(x);
    
             delete[] x;
         }
         catch (...)
         {
             delete[] x;
             throw;
         }
    }
    or instead we could just write
    Code:
    void SomeFunc(void)
    {
        std::vector<int> x(100);
    
        SomeOtherFunc(x);
    
    }
    
    struct big
    {
        double d[100000];
    }
    
    void SomeOtherFunc(std::vector<int> & p)
    {
        for (int i = 0; i < p.size(); i++)
        {
             p[i] = i;
        }
    
        std::vector<big> reallyBig(100000);
    
        if (!ConnectToInternet())
        {
             throw Unconnected();
        }
    
    }
    I know which one is safer. I know which one is cleaner. I know which one is more extensible and I know which I'd prefer.

    Feel free to keep using dynamic arrays.

    and while I'm at it...
    Quote Originally Posted by samGwilliam View Post
    I just don't like relying too much on other people's code.
    That statement is completely backwards. I don't like relying on my own code. I much prefer to use some existing code that's been tested and documented.

    did it take you long to write your own os? your own compiler? browser? ok maybe that's pushing it, but have you written your own versions of cout/printf? ever written a gui library?
    Last edited by ChaosEngine; 07-10-2007 at 03:36 PM.
    "I saw a sign that said 'Drink Canada Dry', so I started"
    -- Brendan Behan

    Free Compiler: Visual C++ 2005 Express
    If you program in C++, you need Boost. You should also know how to use the Standard Library (STL). Want to make games? After reading this, I don't like WxWidgets anymore. Want to add some scripting to your App?

  14. #29
    Registered User samGwilliam's Avatar
    Join Date
    Feb 2002
    Location
    Newport
    Posts
    382
    Not of chars. Clearly I wasn't reading the posts properly. I'd just use a bog-standard array, obviously.

    But if a flexible, dynamic method of storage was really that important then I'd use a linked list.

    What of it?

  15. #30
    Registered User samGwilliam's Avatar
    Join Date
    Feb 2002
    Location
    Newport
    Posts
    382
    Quote Originally Posted by ChaosEngine View Post
    Really? let's have a look at a piece of code then.
    Code:
    void SomeFunc(void)
    {
        int *x = new int[100];
    
        SomeOtherFunc(x);
    
    
        delete[] x;
    }
    we've allocated some memory, called a function, deleted our memory like a responsible programmer and all is happy in the valleys, right?

    but let's have a look at SomeOtherFunc()
    Code:
    struct big
    {
        double d[100000];
    }
    
    void SomeOtherFunc(int *p)
    {
        for (int i = 0; i < 200; i++)
        {
             p[i] = i;
        }
    
        big *reallyBig = new big[100000];
    
        // some code
    
        delete[] big;    
    }
    ok this code has 2 problem (apart from not doing anything useful). The first is that we've overwritten the bounds of our array. Not such a big deal, we should've passed in the size of the array, but it wouldn't necessary with a vector (which knows it's size).

    The second is a bit trickier. You see, there's a very good chance that we don't have enough memory to allocate reallyBig. On a standards-compliant compiler, that means an std::bad_alloc exception will be thrown. Now we're in really big trouble since x will not be deleted.

    ok, but we can catch the exception! so let's rewrite SomeFunc
    Code:
    void SomeFunc(void)
    {
        int *x;
        try
        {
             x = new int[100];
    
             SomeOtherFunc(x);
    
             delete[] x;
         }
         catch (std::bad_alloc &)
         {
             delete[] x;
         }
    }
    ahh, much better. except, we've swallowed the exception so the caller of SomeFunc doesn't know it failed. No problem, let's rethrow the exception.

    Code:
    void SomeFunc(void)
    {
        int *x;
        try
        {
             x = new int[100];
    
             SomeOtherFunc(x);
    
             delete[] x;
         }
         catch (std::bad_alloc &)
         {
             delete[] x;
             throw;
         }
    }
    phew! dodged that bullet. except now another coder has changed SomeOtherFunc()!

    Code:
    struct big
    {
        double d[100000];
    }
    
    void SomeOtherFunc(int *p)
    {
        for (int i = 0; i < 200; i++)
        {
             p[i] = i;
        }
    
        big *reallyBig = new big[100000];
    
        if (!ConnectToInternet())
        {
             throw Unconnected();
        }
    
        delete[] big;    
    }
    ahh crap, now we have to add another catch clause. That sucks. To hell with that, let's just catch all exceptions.
    Code:
    void SomeFunc(void)
    {
        int *x;
        try
        {
             x = new int[100];
    
             SomeOtherFunc(x);
    
             delete[] x;
         }
         catch (...)
         {
             delete[] x;
             throw;
         }
    }
    or instead we could just write
    Code:
    void SomeFunc(void)
    {
        std::vector<int> x(100);
    
        SomeOtherFunc(x);
    
    }
    
    struct big
    {
        double d[100000];
    }
    
    void SomeOtherFunc(std::vector<int> & p)
    {
        for (int i = 0; i < p.size(); i++)
        {
             p[i] = i;
        }
    
        std::vector<big> reallyBig(100000);
    
        if (!ConnectToInternet())
        {
             throw Unconnected();
        }
    
    }
    I know which one is safer. I know which one is cleaner. I know which one is more extensible and I know which I'd prefer.

    Feel free to keep using dynamic arrays.

    and while I'm at it...

    That statement is completely backwards. I don't like relying on my own code. I much prefer to use some existing code that's been tested and documented.

    did it take you long to write your own os? your own compiler? browser? ok maybe that's pushing it, but have you written your own versions of cout/printf? ever written a gui library?
    I didn't read a single line of that (and I'm not going to), but it's entertaining to see just how much I've gotten under your skin!!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Reiventing the wheel (again)
    By Elysia in forum C++ Programming
    Replies: 5
    Last Post: 12-02-2007, 03:26 AM
  2. my mouse wheel
    By DavidP in forum Tech Board
    Replies: 0
    Last Post: 11-06-2006, 09:58 AM
  3. Problems with mouse wheel...
    By xkrja in forum Windows Programming
    Replies: 1
    Last Post: 09-12-2006, 02:22 PM
  4. Logitech MOMO wheel broke, fixed manually
    By Xei in forum Tech Board
    Replies: 2
    Last Post: 07-25-2003, 02:29 AM
  5. Mouse Wheel In Console
    By GaPe in forum C Programming
    Replies: 0
    Last Post: 09-07-2002, 02:05 AM