简体   繁体   English

函数返回类型:指针,参考或其他?

[英]Function Return Type: Pointer, Reference or something else?

Let us assume I always need the direkt return type of the function to be of a errorcode (success of calculation or failure) , then I will return some arguments as parameters. 让我们假设我总是需要函数的direkt返回类型为错误代码(计算成功或失败),然后我将返回一些参数作为参数。 Is it better to define them as reference (and create them before empty) or better to return pointer? 将它们定义为引用(并在空前创建它们)或更好地返回指针是否更好?

Edit: I should be more precise: The errorcode is obligatory because I have to stick to the coding guidline given. 编辑:我应该更精确:错误代码是强制性的,因为我必须坚持给出的编码指南。

Possibility A: 可能性A:

ErrorCode func( some_parameters ... , ReturnType & result)
...
ReturnType result; // empty constructor, probably not good practice
func( some_parameters ..., result)

Possibility B: 可能性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

Even better: Maybe you have a more appropriate solution? 更好的是:也许你有更合适的解决方案?

Edit: Please indicate which standard you are using, since unfortunatelly (guidelines) I have to stick to C++98. 编辑:请说明你正在使用哪个标准,因为不幸(指南)我必须坚持使用C ++ 98。

I would do the following (and in general do) 我会做以下(一般来说)

1.) throw an exception instead of returning error codes 1.)抛出异常而不是返回错误代码

if this is not possible (for any reason) 如果这是不可能的(出于任何原因)

2.) return the pointer directly (either raw or std::unique_ptr) and return nullptr for failure 2.)直接返回指针(raw或std :: unique_ptr)并返回nullptr失败

if return type has to be bool or not all objects returned are (pointers / heap allocated) 如果返回类型必须是bool或者没有返回所有对象(指针/堆已分配)

3.) return your error code (bool or enum class) and accept a reference parameter for all objects that are to be initialized (must have objects so to speak) and pointers to objects that may be optionally created / initialized 3.)返回你的错误代码(bool或enum类)并接受所有要初始化的对象的引用参数(必须有对象可以说)和指向可以选择创建/初始化的对象的指针

if the object cannot be created in advance to the call (eg because it is not default constructible) 如果无法在调用之前创建对象(例如,因为它不是默认构造)

4.) pass a reference to a pointer (raw or std::unique_ptr) or a pointer to a pointer, which will then be filled by the function 4.)传递对指针(raw或std :: unique_ptr)的引用或指向指针的指针,然后由函数填充

std::optional (or similar) may be an option if you only have a true/false return code. 如果您只有一个true / false返回码,则std :: optional(或类似)可能是一个选项。

I don't like returning std::pair or std::tuple because it can make your code look quite annoying if you have to start using .first/.second or std::get<>() to access your different return types. 我不喜欢返回std :: pair或std :: tuple,因为如果你必须开始使用.first / .second或std :: get <>()来访问你的不同返回类型,它会让你的代码看起来很烦人。 Using std::tie() can reduce this a little bit, but it is not (yet) very comfortable to use and prevents the use of const. 使用std :: tie()可以减少这一点,但它(但是)使用起来并不舒服,并且可以防止使用const。

Examples: 例子:

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 ...
     }
 }

Edit: And in general it is advisable to keep your API consistent, so if you already have a medium or large codebase, which makes use of one or the other strategy you should stick to that (if you do not have good reasons not to). 编辑:一般情况下建议保持API的一致性,所以如果你已经有一个中型或大型代码库,那么你应该坚持使用一种或另一种策略(如果你没有充分的理由不这样做) 。

This is a typical example for std::optional . 这是std::optional的典型示例。 Sadly it isn't available yet, so you want to use boost::optional . 可悲的是它还没有,所以你想使用boost::optional

This is assuming that the result is always either "success with result" or "fail without result". 这假设结果总是“成功结果”或“失败没有结果”。 If your result code is more complicated you can return 如果您的结果代码更复杂,您可以返回
std::pair<ResultCode, std::optional<ReturnType>> . std::pair<ResultCode, std::optional<ReturnType>>

It would be good style to to use the return value for all return information. 对所有返回信息使用返回值是一种好方法。 For example: 例如:

std::tuple<bool, ReturnType> func(input_args....)

Alternatively, the return type could be std::optional (or its precursor) if the status code is boolean, with an empty optional indicating that the function failed. 或者,如果状态代码是布尔值,则返回类型可以是std::optional (或其前缀),其中一个空的optional表示函数失败。

However, if the calculation is supposed to normally succeed, and only fail in rare circumstances, it would be better style to just return ReturnType , and throw an exception to indicate failure. 但是,如果计算通常成功,并且只在极少数情况下失败,那么返回ReturnType会更好,并抛出异常以指示失败。

Code is much easier to read when it doesn't have error-checking on every single return value; 当代码没有对每个返回值进行错误检查时,代码更容易阅读; but to be robust code those errors do need to be checked somewhere or other. 但要成为健壮的代码,需要在某处或其他地方检查这些错误。 Exceptions let you handle a range of exceptional conditions in a single place. 例外情况可让您在一个地方处理各种异常情况。

不知道它是否适用于你的情况,但如果你只有两个状态返回类型,那么可能只是从你的函数返回指针然后测试它是否为nullptr?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM