C ++如何检测何时将nullptr传递给期望std :: string的函数?

时间:2014-01-21 21:14:50

标签: c++ string nullptr

我无法找到线程给出明确答案 -

我有一个构造函数,例如:

FanBookPost::FanBookPost(Fan* owner, std::string content);

粉丝是我的代码中的另一个类,但内容是有问题的:

由于std :: string不是指针,我希望用(fan,nullptr)调用构造函数是不可能的。但是,它编译! ...并在运行时使用EXC_BAD_ACCESS崩溃。

这是可以避免的吗?

4 个答案:

答案 0 :(得分:3)

这里的问题是当调用std::string的构造函数时(因为在那里访问了解释为const char*的nullptr),将发生崩溃。这里没有什么可以对付这个但是告诉其他人不要做什么。它不是你的构造函数的问题,因此不是你的责任(除了你不能阻止它)。

答案 1 :(得分:3)

您所观察到的是,您可以从字符指针(在这种情况下为std::string)隐式创建nullptr,然后将其传递给函数。但是,不允许从空指针创建string。您的方法签名没有任何问题,只是客户端使用违反了std::string构造函数的合同。

答案 2 :(得分:1)

如果您真的想要安全,请使用代理/包装器如何:

template<typename T>
struct e_t
{
public:
    inline e_t ( e_t const & other )
        : m_value( other.m_value )
    {}

    inline T & value( void )                { return m_value; }
    inline operator T&()                    { return m_value;   }
    inline e_t( const T& c ) : m_value( c )     {}

private:
    T m_value;
};

void FanBookPost(int* owner, e_t<std::string> content) {
}

int main()
{
    int n = 0;
    //FanBookPost(&n, 0); // compiler error
    //FanBookPost(&n, nullptr); // compiler error
    //FanBookPost(&n, ""); // unfortunately compiler error too
    FanBookPost(&n, std::string(""));
}

答案 3 :(得分:1)

问题是std::string有一个非显式的ctor,它以char *为唯一(必需)参数。这提供了从nullptrstd::string的隐式转换,但提供了未定义的行为,因为该ctor特别需要非空指针。

有几种方法可以防止这种情况发生。可能最有效的方法是对std::string采用(非常量)引用,这需要传递(非临时)string作为参数。

FanBookPost::FanBookPost(Fan* owner, std::string &content);

这确实令人遗憾的是让函数能够修改传递的字符串的副作用。这也意味着(使用符合标准的编译器 1 ),您无法将nullptr 字符串文字传递给函数 - 您和#39;我必须传递std::string的实际实例。

如果您希望能够传递字符串文字,则可以添加一个带有char const *参数的重载,也可以添加带有nullptr_t参数的重载。前者会在创建字符串并调用引用字符串的函数之前检查非空指针,而后者会执行类似记录错误并无条件地终止程序的操作(或者,可能会记录错误并抛出异常)。

这令人烦恼和不方便,但可能优于目前的状况。


  1. 不幸的是,我最后一次注意到MS VC ++在这方面并不符合。它允许通过非const引用传递临时对象。通常这是相当无害的(它只是让你修改临时,但通常没有可见的副作用)。在这种情况下,它会更麻烦,因为你专门依赖它来防止传递临时物体。