C ++字符串,可以为NULL

时间:2008-12-04 19:24:08

标签: c++ string null

我习惯在C ++应用程序中传递这样的字符串:

void foo(const std::string& input)
{
  std::cout << input.size() << std::endl;
}

void bar()
{
  foo("stackoverflow");
}

现在我有一个案例,我希望字符串为NULL:

void baz()
{
  foo("stackoverflow");
  foo(NULL); // very bad with foo implementation above
}

我可以将foo更改为:

void foo(const std::string* input)
{
  // TODO: support NULL input
  std::cout << input->size() << std::endl;
}

但要传递字符串文字或将char*复制到foo的实现,我需要写这样的内容:

void bar()
{
  string input("hi"); // annoying temporary
  foo(&input);
  foo(NULL);  // will work as long as foo handles NULL properly
}

我开始考虑继承std::string并添加null属性,但我不太确定这是个好主意。也许最好简单地使用const char*字符串作为可以为NULL的参数,但是如果我想保存字符串的副本(或NULL)而不必自己管理它的内存呢? (见What are some of the drawbacks to using C-style strings?等)

任何聪明的解决方案?

7 个答案:

答案 0 :(得分:20)

如果您希望类型为null,则将其设为指针。传递字符串指针而不是引用,因为这正是指针可以做的,并且引用不能。引用始终指向同一个有效对象。指针可以设置为null,或者重新指向另一个对象。因此,如果你需要指针可以做的事情,请使用指针。

或者,使用boost :: optional,它允许更类型安全的方式来指定“此变量可能包含或不包含值”。

或者,当然,更改语义,因此您可以使用空字符串而不是null,传递一个单独的bool参数,指定字符串是否可用,或者重构,这样您就不需要这样做了。< / p>

答案 1 :(得分:11)

就个人而言,我会改变语义来传递空的std :: strings而不是NULL:

void foo(const std::string& input)
{
    if (!input.empty())
        std::cout << input.size() << std::endl;
}

void bar()
{
      foo("");
}

答案 2 :(得分:11)

功能超载救援......

void foo( const std::string& input )
{
    std::cout << input << std::endl;

    // do more things ...
}

void foo( const char* input )
{
    if ( input != NULL ) foo( std::string(input) );
}

这将接受c样式字符数组和std ::字符串,如果传入字符串文字或字符数组,将在堆栈上产生额外开销,但允许您将实现保留在一个位置并保持你的语法很好。

答案 3 :(得分:3)

或者,混合一点前两个答案:

void fooImpl( const char* input )
{
    if ( input != NULL )
        std::cout << input << std::endl;
}

void foo( const std::string& input )
{
    fooImpl(input.c_str());    
}

void foo( const char* input )
{
    fooImpl(input);
}

相同的接口,堆栈上没有副本。如果你愿意的话,你也可以内联fooImpl。

答案 4 :(得分:2)

为什么不重载函数并给第二个重载没有参数?然后,两个重载都可以在内部调用一个提供读取逻辑的函数,并且它本身会传递一个指向std::string的指针。

void foo_impl(string const* pstr) { … }

void foo(string const& str) {
    foo_impl(&str);
}

void foo() {
    foo_impl(0);
}

答案 5 :(得分:2)

绝对不要继承std::string。继承是你在C ++中可以拥有的最紧密的耦合,而你只是在寻找可空性,如果你真的想要的话,你只需要const char*,重载或简单地std::string *

答案 6 :(得分:1)

如果你只是使用:

void foo(const char *xinput)
{
    if (xinput == NULL) {
        // do something exceptional with this
        return;
    }
    std::string input(xinput);
    // remainder of code as usual
}

是的,这会产生额外的分配和复制,并且调用该函数有点冗长,因为在通常情况下需要使用.c_str(),但它确实为您提供了所需的语义。