views:

159

answers:

3

I was wondering, I normally use std::string for my code, but when you are passing a string in a parameter for a simply comparison, is it better to just use a literal?

Consider this function:

bool Message::hasTag(string tag)
{
    for(Uint tagIndex = 0; tagIndex < m_tags.size();tagIndex++)
    {
        if(m_tags[tagIndex] == tag)
            return 0;
    }

    return 1;
}

Despite the fact that the property it is making a comparison with is a vector, and whatever uses this function will probably pass strings to it, would it still be better to use a const char* to avoid creating a new string that will be used like a string literal anyway?

+14  A: 

If you want to use classes, the best approach here is a const reference:

bool Message::hasTag(const string& tag);

That way, redudant copying can be minimized and it's made clear that the method doesn't intend to modify the argument. I think a clever compiler can emit pretty good code for the case when this is called with a string literal.

Passing a character pointer requires you to use strcmp() to compare, since if you start comparing pointers directly using ==, there will be ... trouble.

unwind
It will have to construct a string object, no matter how clever the compiler is.
anon
ctinnist
@ctinnist: If you're passing a reference (or a pointer) to a `string` object, you still have to have a `string` object at some point.
Frerich Raabe
@ ctinnist No, it doesn't.
anon
@Frerich: well, yes, otherwise you'll need to have a char* array somewhere... the OP is concerned about implicit copies when passing strings to functions, not the object creation itself.
rubenvb
`Passing a character pointer requires you to use strcmp()`: comparing two `std::strings` has to compare both strings character by character as well, so passing a `std::string` doesn't offer any improvement there.
Frerich Raabe
@Frerich: of course there is an improvement, m_tags[tagIndex] == tag is easier to read (shorter) than strcmp(m_tags[tagIndex], tag) == 0. I'm not saying there's a *performance* improvement, I never tried to imply that all characters don't have to be inspected.
unwind
@unwind: `m_tags[tagIndex]` apparently already contains strings, judging from the code in the question. Hence, you don't need `strcmp` at all. Just continue using `m_tags[tagIndex] == tag` (using the `const char *` overload of the comparison operator).
Frerich Raabe
A: 

I think it would be enough to pass an reference rather than value of string. I mean:

bool Message::hasTag(const string& tag)

That would copy only the reference to the original string value. Which must be created somwhere anyway, but outside of the function. This function would not copy its parameter whatsoever.

Since m_tags is a vector of strings anyway (I suppose), const string& parameter would be better idea.

Archie
+1  A: 

Short answer: it depends.

Long answer: std::string is highly useful because it provides a lot of utility functions for strings (searching for substrings, extracting substrings, concatenating strings etc.). It also manages the memory for you, so the ownership of the string cannot be confused.

In your case, you don't need either. You just need to know whether any of the objects in m_tags matches the given string. So for your case, writing the function using a const char *s is perfectly sufficient.

However, as a foot note: you almost always want to prefer std::string over (const) char * when talking about return values. That's because C strings have no ownership semantics at all, so a function returning a const char * needs to be documented very carefully, explaining who owns the pointed to memory (caller or callee) and, in case the callee gets it, how to free it (delete[], delete, free, something else).

Frerich Raabe