Phi*_*ati 1 c++ validation optimization code-duplication
我想在我的构造函数中抛出异常,这样我就不必处理僵尸对象了.但是,我还想提前提供验证方法,以便人们可以避免在没有原因的情况下"处理异常".在GUI中,期望无效数据并不例外.但是我也想避免代码重复和开销.GCC/Microsoft Visual C++编译器是否足够聪明,可以消除两次验证输入的低效率,如果没有,是否会有一个微妙的变化可以取悦?
我的观点的示例代码块如下:
#include <string>
#include <exception>
#include <iostream>
using std::string;
using std::cout;
using std::endl;
using std::exception;
// a validation function
bool InputIsValid(const string& input) {
return (input == "hello");
}
// a class that uses the validation code in a constructor
class MyObject {
public:
MyObject(string input) {
if (!InputIsValid(input)) //since all instances of input
throw exception(); //has already been validated
//does this code incur an overhead
//or get optimised out?
cout << input << endl;
};
};
int main() {
const string valid = "hello";
if (InputIsValid(valid)) {
MyObject obj_one(valid);
MyObject obj_two(valid);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我预计如果类的目标文件是单独生成的话可能不可能,因为目标文件无法确保人们在调用构造函数之前会验证,但是当在单个应用程序中编译和链接应用程序时,是不是可能吗?
如果所有数据可能已经有效,是否存在在构造函数中验证的开销?
是的,如果数据已经过验证,那么您将需要再次验证数据
GCC/Microsoft Visual C++编译器是否足够聪明,可以消除两次验证输入的低效率,如果没有,是否会有一个微妙的变化可以取悦?
您可以将输入封装在对象中,该对象将记住验证结果.
template <typename INPUT_TYPE>
class InputObject {
INPUT_TYPE input_;
bool valid_;
public:
typedef <typename VALIDATE>
InputObject (INPUT_TYPE in, VALIDATE v) : input(in), valid_(v(in)) {}
const INPUT_TYPE & input () const { return input_; }
bool isValid () const { return valid_; }
};
typedef InputObject<std::string> MyInput;
class MyObject {
public:
MyObject (const MyInput &input) {
if (!input.isValid()) throw exception();
//...
}
};
Run Code Online (Sandbox Code Playgroud)
构造InputObject函数为您调用验证器函数,并将验证结果存储在标志中.然后MyObject只检查标志,而不必再次进行验证.
int main () {
MyInput input("hello", InputIsValid);
try {
MyObject obj_one(input);
MyObject obj_two(input);
}
catch (...) {
//...
}
}
Run Code Online (Sandbox Code Playgroud)
正如DeadMG所建议的那样,通过坚持MyObject只接受经验证的输入,可以实现更强的类型检查.然后,它根本不需要throw在构造函数中.这种方案可以通过制作NonValidatedInput和ValidatedInput两种不同类型来实现.
template <typename> class NonValidatedInput;
template <typename T>
class ValidatedInput {
friend class NonValidatedInput<T>;
T input;
ValidatedInput (const T &in) : input(in) {}
public:
operator const T & () const { return input; };
};
template <typename T>
class NonValidatedInput {
T input;
public:
operator ValidatedInput<T> () const { return ValidatedInput<T>(input); }
template <typename V>
NonValidatedInput (const T &in, V v) : input(in) {
if (v(input) == false) throw exception();
}
};
Run Code Online (Sandbox Code Playgroud)
NonValidatedInput接受未验证的输入,并执行验证,ValidatedInput如果验证成功,则可以转换为对象.如果验证失败,则NonValidatedInput抛出异常.因此,MyObject根本不需要检查验证,因为它的构造函数只接受ValidatedInput.
typedef ValidatedInput<std::string> MyInput;
class MyObject {
public:
MyObject (MyInput input) {
std::string v = input;
std::cout << v << std::endl;
}
};
int main () {
try {
MyInput input = NonValidatedInput<std::string>("hello", InputIsValid);
MyObject obj_one(input);
MyObject obj_two(input);
}
catch (...) {
//...
}
}
Run Code Online (Sandbox Code Playgroud)
这里的类型安全性非常强,因为只有在验证成功的情况下NonValidatedInput才能创建ValidatedInput.