Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ constructors and implicit string conversion

In c++, I can write a class with a constructor that takes a std::string parameter. This will allow me to construct instances of this class from either std::string or char *, due to implicit conversions.

Is there ever a reason to have both a std::string constructor and a char * constructor?

class MyStringClass {
 public:
    MyStringClass( const std::string &str ); // char *'s could implicitly use this constructor
    MyStringClass( const char * str );       // would this ever be necessary?
};

This question also applies to function arguments.

void do_stuff_with_string( const std::string &str );
void do_stuff_with_string( const char * str );

Edit:

To clarify, I am wondering more about the performance. Say these constructors/functions are calling into api's that only take char *. Is it worth it to have the two separate functions to avoid constructing a std::string if I don't have to?

void do_stuff_with_string( const std::string &str )
{
    do_stuff_with_string( str.c_str() );
}

void do_stuff_with_string( const char * str )
{
    // call some api that only accepts char *
}
like image 642
Brian Schlenker Avatar asked Jun 05 '14 18:06

Brian Schlenker


People also ask

How can we use constructor to convert types?

Conversion constructor in C++? The constructors are used to construct objects of a class. Sometimes constructors may take some arguments, or sometimes it does not take arguments. When a constructor takes only one argument then this type of constructors becomes conversion constructor.

What is a conversion constructor?

A conversion constructor is a single-parameter constructor that is declared without the function specifier explicit . The compiler uses conversion constructors to convert objects from the type of the first parameter to the type of the conversion constructor's class.

Which is keyword is used with constructors to prevent type conversion?

Explicit Keyword in C++ is used to mark constructors to not implicitly convert types in C++.

What is implicit default constructor?

A default constructor is a constructor that either has no parameters, or if it has parameters, all the parameters have default values. If no user-defined constructor exists for a class A and one is needed, the compiler implicitly declares a default parameterless constructor A::A() .


1 Answers

You'd need to overload your constructors if you wished to handle a C-string and an std::string differently.

MyStringClass::MyStringClass( const std::string &str )
{
    // Do std::string-specific stuff here.
}

MyStringClass::MyStringClass(const char * str )
{
    // Do char* specific stuff here.
}

There's also the possibility that a parameter of const char * is not a null-terminated C-string, but in fact a pointer to a single character, or a non-null-terminated character array. In this case, an implicit conversion might fail.

Example:

#include <iostream>

int DoStuff(const std::string &myString)
{
    std::cout << myString << std::endl;
}

int main()
{
    DoStuff("This is a null terminated c-string");  // Fine!

    char charArray[] = { 'A', 'B', 'C' };           // Not null terminated!
    DoStuff(charArray);                             // Uh oh!
}

The example above is for a function, but the same could be applied to a constructor too. The above example compiles without warnings!

In terms of performance, there is certainly a hit due to the fact that an std::string(const char * const) constructor will copy the c-string into it's own internal buffer. However in most cases the impact will be negligible since the copy is extremely efficient. With very large strings however, it could be an issue.

As a general rule though, try to work with C++ strings as much as possible, and use the std::string::c_str() member when C-style strings are required. The occasional string copy from char* to std::string will be a micro-optimization in most cases. Only in very performance-critical code would this be a potential concern.

like image 134
Karl Nicoll Avatar answered Oct 06 '22 00:10

Karl Nicoll