-3

I have copied this code from a site. But I am having problems understanding it properly. Please can you help me these doubts. I have written them as comments.

#include<iostream>
using namespace std;
#include<cstring>
class strings
{
    char *m_string;   
    int m_length;
    public:
        strings(const char* str = "")    
        {
            m_length = strlen(str) + 1;

            m_string = new char[m_length];

            strncpy(m_string,str,m_length);

            m_string[m_length - 1] = '\0';/*1*/
        }
        ~strings()  /*2*/
        {
            delete[] m_string;

            m_string = 0;/*3*/
        }
        char* get()
        {
            return m_string;
        }
};

int main()
{
    strings cstring("Alex");
    cout << "Hi I am " << cstring.get();
    cout << "\nsup";
    strings cstrings1("Shady");
    cout << "\nyo " << cstrings1.get();
    return 0;
}
  1. why is the code asking me to do this. When I removed this line code still worked perfectly fine
  2. why are they using the destructor? Again not using it does seem to have any effect on the program
  3. Also what is the use of doing this when I just used the delete keyword

Can you guys please explain to me in easy way really what do I use a destructor for? Thank you so much

David Guyon
  • 2,759
  • 1
  • 28
  • 40
  • 1
    I suggest you don't copy any more code from that site, and learn the principles of [RAII](http://stackoverflow.com/questions/2321511) and [copy semantics](http://stackoverflow.com/questions/4172722), and the use of [`std::string`](http://en.cppreference.com/w/cpp/string) rather than ugly, error-prone C-style idioms. – Mike Seymour Feb 23 '15 at 15:30
  • 2
    One general note, just because the code works when you make a random change, does not mean it's fine. I call it monkeywrench testing (and I don't think I invented the term, but I can't find reference). If you throw a monkeywrench into some machinery it does not mean it will blow up immediately, but it might when you least expect it, and you would like the machine to tell something is messing up with it. Undefined behaviour is like kind of like points in "Whose Line is it Anyway" anything can happen. – luk32 Feb 23 '15 at 15:31
  • 1
    The code is doing what it should. What you should do is finish your book on C++ before asking those questions. It will explain things better than we could here. – sashoalm Feb 23 '15 at 15:36
  • @luk32 The common term for this is _shotgun debugging_ I believe :). – Rerito Feb 23 '15 at 15:37
  • But the site said that I don't need to define the destructor explicitly in most cases?Why then do I need to do that when I am using dynamic allocation? – user2546419 Feb 23 '15 at 15:51
  • @Rerito The thing I am referring to actually has a different aim but it's clearly related and could probably be used as an equivalent in this context. It's not to get rid of bug but to ensure that causing one is visible. Changing logic should be caught immediately - so the shotgun debugging would have no purpose. You throw in a monkeywrench and expect a graceful slap, not a blow up, not nothing. This is not a design thing with c and c++, you just silently go into UB, thus removing `-1` from `*1*` might work or not. Higher level languages/frameworks often trade some performance for such safety. – luk32 Feb 23 '15 at 17:01

2 Answers2

0

1) Ensures that the string is null terminated - see http://www.cplusplus.com/reference/cstring/strncpy/ as to why this might not always be the case 2) It allows the delete operator to free up the allocated heap memory - otherwise your program will have a memory leak 3) Just good practice to avoid deleting previously deleted memory - this avoids undefined behaviour.

Ed Heal
  • 59,252
  • 17
  • 87
  • 127
0

This is how to misuse C idioms in C++ to produce dangerous, error-prone programs. Don't use this as an example of how to write C++ effectively. To answer your specific questions:

  1. In this case, explicitly terminating the C-style string is pointless. If you didn't know whether the input was small enough to fit in the array, then strncpy might truncate the string, and not put a zero terminator on the end; so, if you use strncpy, you must either terminate it yourself, or take some other action if it was truncated. But here you just allocated a large enough array, measured using strlen. You might as well use strcpy, memcpy or std::copy (which assume a large enough output array) instead of strncpy. Or, since this is C++ not C, throw the whole thing away and use std::string.

  2. The destructor is needed to deallocate the memory allocated in the constructor. Otherwise you have a memory leak. As you say, this doesn't seem to have an effect - unless the program keeps allocating and leaking memory, in which case you'll eventually run out. You'll also need to define or delete a copy constructor and copy-assignment operator (per the Rule of Three), otherwise the class is not safe to copy.

  3. That's pointless, since the pointer itself is about to be destroyed along with the rest of the class object. In some circumstances, if the pointer is going to persist after the delete, setting it to null would allow you to check whether or not it points to anything. But, unless you enjoy long debugging sessions, you shouldn't be using pointers for memory management anyway; use RAII types like smart pointers or std::string.

Community
  • 1
  • 1
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644