我正在创建一个具有从const char*
初始化的构造函数的类,它应该使用缓冲区中提供的应该包含字符串的数据安全地构造对象。我担心的是,用户可以将此构造函数与错误数据一起使用,例如NULL
指针或指向未分配内存的指针或类似的东西。关键是,在这种情况下,我想完成创建对象(它将处于未定义但正确的状态),而不会导致段错误,例如,如果用户向我发送了指向我不应该读取的数据的指针。我想将所有输入验证发送到std::string
构造函数,因此构造函数看起来像这样:
Foo(const char *s) : Foo(std::string(s)) {}
但我的老师称这是一个“错误的想法”。那么,处理这种情况的正确方法是什么呢?
还有一件事,我不能在这种情况下使用例外(这是我课程作业的一部分,当然还没有教过它)。
答案 0 :(得分:7)
问题是有一些你绝对无法检查的事情。该组中最大的一个是指向无效内存的指针。例如:
char* blarg = new char[50];
delete blarg;
Foo(blarg);
Here是关于你所问的问题的另一个对话。有一些好的答案,但他们基本上说同样的事情。处理指针输入时,无法100%确定用户没有做过愚蠢的事情,比如在传入之前调用指针上的删除。
答案 1 :(得分:2)
我担心的是,用户可以将此构造函数与错误的数据一起使用,例如NULL指针或指向未分配内存的指针或类似的东西。关键是,在这种情况下,我想完成创建对象(它将是未定义但正确的状态)
无法检测指针是否有效。调用者必须负责保证它指向已分配的内存。
但是,可以检测指针是否为空。您可以检查它,如果是,则设置对象的状态而不取消引用指针。
我想过将所有输入验证发送到std :: string构造函数
但我的老师称这是一个“错误的想法”。
你的老师是对的。这无济于事,因为std::string
也需要并假设输入有效。使用无效指针构造它会导致未定义的行为。
那么,处理这种情况的正确方法是什么呢?
简单地要求呼叫者保证指针的有效性是正确的 - 并且你能做到 - 。如果你想检查null,请随意这样做。
答案 2 :(得分:0)
如果构造函数中有错误throw
。这就是它的用途。对象不是构造的,并且客户端(传入错误指针的人)被正确地告知了。
答案 3 :(得分:0)
如果您想检查您的班级仅接受std::string
作为参数
和const char[]
你可以这样写:
class Foo {
public:
template<typename U>
Foo(U &&val, typename std::enable_if<std::is_same<typename std::remove_reference<U>::type, std::string>::value ||
std::is_array<typename std::remove_reference<decltype(val)>::type>::value, void>::type* = nullptr): field_(val) {}
private:
std::string field_;
};
然后:
Foo foo("aa");//accept
std::string str("bb");
Foo foo2(str);//accept
Foo fnull(NULL);//compile time error
当然,如果你想只传递指向char
的指针,这个解决方案就不起作用了。