C ++构造函数和隐式字符串转换

时间:2014-06-05 18:09:23

标签: c++ string function class implicit-conversion

在c ++中,我可以编写一个带有std::string参数的构造函数的类。由于隐式转换,这将允许我从std::stringchar *构建此类的实例。

是否有理由同时拥有std::string构造函数和char *构造函数?

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

这个问题也适用于函数参数。

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

编辑:

为了澄清,我想知道更多关于性能的信息。假设这些构造函数/函数正在调用只接受char *的api。如果我不需要这两个单独的函数来避免构造std::string,是否值得?

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 *
}

3 个答案:

答案 0 :(得分:2)

如果您希望以不同的方式处理C字符串和std::string,则需要重载构造函数。

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

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

const char *的参数也可能不是以空字符结尾的C字符串,而实际上是指向单个字符或非空终止字符数组的指针。在这种情况下,隐式转换可能会失败。

示例:

#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!
}

上面的示例是针对函数的,但同样也可以应用于构造函数。上面的例子编译没有警告!

就性能而言,由于std::string(const char * const)构造函数将c-string复制到其自己的内部缓冲区中,因此肯定会受到打击。但是,在大多数情况下,影响可以忽略不计,因为副本非常有效。然而,对于非常大的字符串,它可能是一个问题。

作为一般规则,尝试尽可能使用C ++字符串,并在需要C样式字符串时使用std::string::c_str()成员。在大多数情况下,偶然从char*std::string的字符串副本将是微优化。只有在性能非常关键的代码中,这才是一个潜在的问题。

答案 1 :(得分:0)

是的,假设你想释放构造函数中char *字符串所占的内存。在这种情况下,您需要两个不同的构造函数。

答案 2 :(得分:0)

如果您正在使用需要(const)char * 函数参数的C API,则通常(也)您希望提供(const)char * C风格的界面。

例如,考虑一下iconv(3)的RAII包装器 Iconv 。在 Iconv的初始化中,您需要包装

iconv_t iconv_open(const char* tocode, const char* fromcode);

您真的要让 Iconv的(仅)构造器成为

Iconv(const std::string& tocode, const std::string& fromcode);

尤其是您的参数(tocode,fromcode)最有可能来自命令行(argv)吗?

在这种情况下,为方便起见,我将定义相应的C样式构造函数(可能还会定义前一个)(然后通过std :: string :: c_str()调用C样式构造函数)。