这篇文章主要讲解了“C++返回多个输出值时为什么最好返回结构体或tuple”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++返回多个输出值时为什么最好返回结构体或tuple”吧!
返回值本身就表明了自己是一个只用作输出的值。注意C++是可以同时返回多个值的,通常是使用tuple(包括pair),调用者还可以利用tie获得额外的便利性。如果返回值有特定的含义时使用命名的结构体会更好。否则无名的tuple会更适合一般的代码。
译者注:tie是C++11导入的新特性,可以用于解构tuple元素。
Example(示例)
// BAD: output-only parameter documented in a comment
int f(const string& input, /*output only*/ string& output_data)
{
// ...
output_data = something();
return status;
}
// GOOD: self-documenting
tuple<int, string> f(const string& input)
{
// ...
return make_tuple(status, something());
}
译者注:类似的返回多值的做法在其他语言(例如Python)中已经广泛使用。
C++98的标准库中已经使用这种风格,因为pair就像2个元素的tuple。例如,假设有一个set<string> my_set,考虑下面的代码:
// C++98result = my_set.insert("Hello");if (result.second) do_something_with(result.first); // workaround
使用C++11你可以这样写,直接将结果放入已经存在的局部变量。
Sometype iter; // default initialize if we haven't already
Someothertype success; // used these variables for some other purpose
tie(iter, success) = my_set.insert("Hello"); // normal return value
if (success) do_something_with(iter);
使用C++17,我们可以使用结构化绑定功能定义和初始化多个值:
if (auto [ iter, success ] = my_set.insert("Hello"); success) do_something_with(iter);
有时我们需要向函数传递一个对象以便控制这个对象的状态。在这种情况下,使用引用T&传递对象通常是正确的方式。一般不需要一方面明确地传递一个输入/输出参数,另一方面却通过返回值输出。例如:
istream& operator>>(istream& is, string& s); // much like std::operator>>()
for (string s; cin >> s; ) {
// do something with line
}
译者注:这里说的应该是s。is由于需要支持连续的>>,需要作为返回值返回。
这里s和cin都用作输入/输出参数。我们通过(非常量)引用传递cin以便控制它的状态。我们传递s以避免重复申请内存。通过重用s(通过引用传递),我们只是在需要扩充s的容量时重新申请内存。这个技术有时被称为“用户申请的输出”模式,这种方式特别适用于类似string和vector那样的类型,它们需要释放申请到的存储空间。
作为比较,如果我们使用返回值传出所有值,差不多需要这样做:
pair<istream&, string> get_string(istream& is); // not recommended
{
string s;
is >> s;
return {is, s};
}
for (auto p = get_string(cin); p.first; ) {
// do something with p.second
}
我们认为这种做法明显不够优雅,也不够高效。
如果真正严格地理解这条准则(F.21), 这个例外并不是真的例外,因为它依赖于输入/输出参数,而不是本准则提到的简单的输出参数。然而我们强调的是
明确而不是隐含地传递的情况。
Note(注意)
很多情况下,传递一个明确的,用户定义的类型可能是有用的。例如:
struct Distance {
int value;
int unit = 1; // 1 means meters
};
Distance d1 = measure(obj1); // access d1.value and d1.unit
auto d2 = measure(obj2); // access d2.value and d2.unit
auto [value, unit] = measure(obj3); // access value and unit; somewhat redundant
// to people who know measure()
auto [x, y] = measure(obj4); // don't; it's likely to be confusing
译者注:代码中[x,y]的用法是C++17中引入的结构化绑定(structred binding)
一般的pair和tuple应该只被用于返回值表现独立实体(数据之间没什么内在联系)的情况,而不是表现某种抽象。
另外一个例子,使用和variant<T, error_code>类似的特定类型,而不是使用一般的tuple。
译者注:variant是C++17引入的新特性。这个例子可以看做抽象之外的另一种包含明确意义的情况。
Enforcement(实施建议)
应该使用返回值代替输出参数。输出参数可以是函数写入动作的对象,调用一个非常量成员函数,或者作为一个非常量传递。
感谢各位的阅读,以上就是“C++返回多个输出值时为什么最好返回结构体或tuple”的内容了,经过本文的学习后,相信大家对C++返回多个输出值时为什么最好返回结构体或tuple这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。