Erika Electra
Erika Electra

Reputation: 1882

Pop() etiquette

Situation: I'm implementing a list-like container that supports a Pop() function that should return the user the const char* stored at the front of the container. However, I'm not sure as an implementer whether or not I should be returning the original const char* (deleting the node pointer from the container but not calling delete on the const char* itself), or whether I should allocate new memory and return a copy of the element.

From class and projects, I've encountered those who espouse always copying, so that no previously returned references (from getters, etc.) and pointers to the const char* can alter the popped version, but since this approach requires an extra allocation and strcpy, I thought I'd ask whether simply returning the original, undeleted pointer to const char without deleting it is really a problem. Here's a code snippet of the approach WITH allocation and copy (and deleting the original reference afterwards):

const char* LinkedList::PopHeadString()
{
    node* deletehead = head_;
    char* output = NULL;

    if (head_ != NULL && GetHeadType() == STRING) {
        output = new char[strlen(head_->en.data.str) + 1];
        strcpy(output, head_->en.data.str);
        head_ = head_->next;
        delete deletehead->en.data.str;
        delete deletehead;
        --nEntries_;
    }
    return output;
}

Since Pop() is a common container operation, I thought I'd ask what the general approach is.

Upvotes: 3

Views: 232

Answers (1)

Björn Pollex
Björn Pollex

Reputation: 76876

If you return the pointer without copying you have to decide who owns the pointer. The one who owns it is responsible for deleting it when it is no longer needed. This can be a very hard problem, especially if your code gets more complex. Copy-semantics are much simpler to reason about.

In your specific example, the first thing to change would be to use std::string instead of const char * to represent strings. If you return an std::string by value, it will take care of the copying for you.

If you really want to prevent the copy, but still manage the lifetime elegantly, you should consider using an std::shared_ptr<std::string> (or boost::shared_ptr<std::string> if you don't have a C++11-compiler). A shared_ptr uses reference-counting to determine when the object it points to should be released, thus taking the burden of manual memory management from you, which is a Good Idea.

Upvotes: 4

Related Questions