2014-06-05 42 views
4

在C++中,我可以用一个构造函数编写一个类,该构造函数需要std::string参数。由于隐式转换,这将允许我从std::stringchar *构造此类的实例。C++构造函数和隐式字符串转换

是否曾有理由同时拥有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 *。如果我不需要,有两个单独的功能来避免构建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 * 
} 
+1

显而易见的原因是,如果你想以不同的方式处理它们。当然,还有其他原因,如果不简单地提供一个清单,就很难回答这个问题。你能给我们提供更多关于你想要做什么的信息吗? –

+0

@CodyGray我想我更多地要求表现。是否值得同时避免构造一个字符串(如果在函数内部,我只使用.c_str()方法),或者开销如此之小,我不应该担心它? –

+0

@CodyGray当你指出你自己保存的是一个字符串的构造。这种开销是否是“分钟”取决于你的程序中如何使用这个类很难在这里回答。 –

回答

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

上面的例子为函数,但同样可以太应用于构造方法。上面的例子编译时没有警告!

在性能方面,由于构造函数会将c字符串复制到它自己的内部缓冲区中,所以确实存在命中。但是在大多数情况下,由于副本非常有效,所以影响可以忽略不计。然而,对于非常大的字符串,这可能是一个问题。

尽管尽可能地尝试使用C++字符串,并且在需要C风格的字符串时使用std::string::c_str()成员。在大多数情况下,偶尔从char*std::string的字符串拷贝将是一个微型优化。只有在性能严格的代码中,这才是潜在的问题。

+0

无论如何,最后一个例子是一个'//哦,哦!'。由于您不会将数组长度作为参数传递,因此您可以直接阅读。函数知道它的唯一方法是找到一个哨兵字符。然后你重新发明了C风格的字符串。 –

+0

@CodyGray - 技术上正确(最好正确)!我的观点是'char *'不一定必须是c字符串,在这种情况下,重载是必要的,在后一种情况下,需要一个长度参数。 –

0

嗯,是的,假设你想释放由构造函数的字符串char *举行的记忆。在这种情况下,你需要两个不同的构造函数。