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 *
}
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.
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.
Explicit Keyword in C++ is used to mark constructors to not implicitly convert types in C++.
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() .
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With