我无法找到线程给出明确答案 -
我有一个构造函数,例如:
FanBookPost::FanBookPost(Fan* owner, std::string content);
粉丝是我的代码中的另一个类,但内容是有问题的:
由于std :: string不是指针,我希望用(fan,nullptr)调用构造函数是不可能的。但是,它编译! ...并在运行时使用EXC_BAD_ACCESS崩溃。
这是可以避免的吗?
答案 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 *
为唯一(必需)参数。这提供了从nullptr
到std::string
的隐式转换,但提供了未定义的行为,因为该ctor特别需要非空指针。
有几种方法可以防止这种情况发生。可能最有效的方法是对std::string
采用(非常量)引用,这需要传递(非临时)string
作为参数。
FanBookPost::FanBookPost(Fan* owner, std::string &content);
这确实令人遗憾的是让函数能够修改传递的字符串的副作用。这也意味着(使用符合标准的编译器 1 ),您无法将nullptr
或字符串文字传递给函数 - 您和#39;我必须传递std::string
的实际实例。
如果您希望能够传递字符串文字,则可以添加一个带有char const *
参数的重载,也可以添加带有nullptr_t
参数的重载。前者会在创建字符串并调用引用字符串的函数之前检查非空指针,而后者会执行类似记录错误并无条件地终止程序的操作(或者,可能会记录错误并抛出异常)。
这令人烦恼和不方便,但可能优于目前的状况。