让我们假设我总是需要函数的direkt返回类型为错误代码(计算成功或失败),然后我将返回一些参数作为参数。将它们定义为引用(并在空前创建它们)或更好地返回指针是否更好?
编辑:我应该更精确:错误代码是强制性的,因为我必须坚持给出编码指南。
可能性A:
ErrorCode func( some_parameters ... , ReturnType & result)
...
ReturnType result; // empty constructor, probably not good practice
func( some_parameters ..., result)
可能性B:
ErrorCode func( some_parameters ... , ReturnType * result){
...
result = new ReturnType(...)
...
}
...
ReturnType * result; // void pointer
func( some_parameters ..., result)
...
delete result; // this is needed if I do not use a smart pointer
更好:也许你有更合适的解决方案?
编辑:请说明您使用的是哪种标准,因为不幸(指南)我必须坚持使用C ++ 98.
答案 0 :(得分:3)
我会做以下(一般情况下)
1。)抛出异常而不是返回错误代码
如果这是不可能的(出于任何原因)
2。)直接返回指针(raw或std :: unique_ptr)并返回nullptr失败
如果返回类型必须是bool,则返回的所有对象都是(指针/堆分配)
3.)返回你的错误代码(bool或enum类)并接受所有要初始化的对象的引用参数(必须有对象)和指向可以选择创建/初始化的对象的指针
如果无法事先为调用创建对象(例如因为它不是默认构造的)
4。)传递对指针(raw或std :: unique_ptr)的引用或指向指针的指针,然后由函数填充
如果你只有一个真/假的返回代码,那么std :: optional(或类似的)可能是一个选项。
我不喜欢返回std :: pair或std :: tuple,因为如果你必须开始使用.first / .second或std :: get<>(),它会让你的代码看起来很烦人访问您的不同退货类型。使用std :: tie()可以减少这一点,但它(但)使用起来并不舒服,并且阻止使用const。
示例:
std::unique_ptr<MyClass> func1() { /* ... */ throw MyException("..."); }
std::unique_ptr<MyClass> func2() { /* ... */ }
ErrorCode func3(MyClass& obj, std::string* info = nullptr) { /* ... */ }
ErrorCode func4(std::unique_ptr<MyClass>& obj) { /* ... */ }
int main()
{
try
{
auto myObj1 = func1();
// use ...
}
catch(const MyException& e)
{
// handle error ...
}
if(auto myObj2 = func2())
{
// use ...
}
MyClass myObj3;
std::string info;
ErrorCode error = func3(myObj3, &info);
if(error == ErrorCode::NoError)
{
// use ...
}
std::unique_ptr<MyClass> myObj4;
ErrorCode error = func4(myObj4);
if(error == ErrorCode::NoError)
{
// use ...
}
}
编辑:一般情况下建议保持API的一致性,所以如果你已经有一个中型或大型代码库,它会使用一种或另一种策略,你应该坚持这一点(如果你没有充分的理由)不要)。
答案 1 :(得分:2)
这是std::optional
的典型示例。可悲的是,它还没有,所以你想使用boost::optional
。
这假设结果总是&#34;成功结果&#34;或&#34;失败而没有结果&#34;。如果您的结果代码更复杂,您可以返回
using (PrincipalContext ad = new PrincipalContext(contextType, adserviceName, adContext, ContextOptions.SimpleBind, username, password))
{
UserPrincipal u = new UserPrincipal(ad) {Name = "*"};
PrincipalSearcher search = new PrincipalSearcher { QueryFilter = u };
// get the underlying "DirectorySearcher"
DirectorySearcher ds = search.GetUnderlyingSearcher() as DirectorySearcher;
if(ds != null)
{
// set the PageSize, enabling paged searches
ds.PageSize = 500;
}
foreach (var principal in search.FindAll())
{
//do something
}
}
。
答案 2 :(得分:2)
对所有返回信息使用返回值将是一种好方法。例如:
std::tuple<bool, ReturnType> func(input_args....)
或者,如果状态代码是布尔值,则返回类型可以是std::optional
(或其前身),空optional
表示函数失败。
但是,如果计算通常应该成功,并且只在极少数情况下失败,那么返回ReturnType
并抛出异常以指示失败将是更好的风格。
当代码没有对每个返回值进行错误检查时,代码更容易阅读;但要成为健壮的代码,需要在某处或其他地方检查这些错误。例外情况可让您在一个地方处理各种异常情况。
答案 3 :(得分:0)
不知道它是否适用于您的情况,但如果您只有两个状态返回类型,那么可能只是从您的函数返回指针然后测试它是否为nullptr?