为什么似乎没有人在C++中使用元组,无论是Boost元组库还是TR1的标准库?我已经阅读了很多C++代码,我很少看到元组的使用,但我经常看到很多地方元组会解决许多问题(通常从函数返回多个值).
元组允许你做这样的各种酷事:
tie(a,b) = make_tuple(b,a); //swap a and b
Run Code Online (Sandbox Code Playgroud)
这肯定比这更好:
temp=a;
a=b;
b=temp;
Run Code Online (Sandbox Code Playgroud)
当然你总能做到这一点:
swap(a,b);
Run Code Online (Sandbox Code Playgroud)
但是如果要旋转三个值怎么办?你可以用元组做到这一点:
tie(a,b,c) = make_tuple(b,c,a);
Run Code Online (Sandbox Code Playgroud)
元组还使得从函数返回多个变量变得更加容易,这可能是比交换值更常见的情况.使用对返回值的引用肯定不是很优雅.
我没有想到的元组有什么大的缺点吗?如果没有,为什么他们很少使用?他们慢了吗?或者只是人们不习惯他们?使用元组是个好主意吗?
Tre*_*son 122
一个愤世嫉俗的答案是许多人用C++编程,但不理解和/或使用更高级别的功能.有时这是因为他们不被允许,但许多人根本不尝试(甚至不理解).
作为一个非增强的例子:有多少人使用的功能<algorithm>?
换句话说,许多C++程序员只是使用C++编译器的C程序员,也许std::vector和std::list.这就是使用boost::tuple不常见的一个原因.
Ala*_*met 40
因为它尚未标准化.任何非标准的都有更高的障碍.由于程序员们吵着要他们,所以Boost的作品变得很受欢迎.(hash_map跳跃于脑海).但是,虽然元组很方便,但人们对它的困扰并不是那么压倒性和明确的胜利.
use*_*714 23
C++元组语法可能比大多数人想要的更冗长.
考虑:
typedef boost::tuple<MyClass1,MyClass2,MyClass3> MyTuple;
Run Code Online (Sandbox Code Playgroud)
因此,如果你想大量使用元组,你可以在任何地方获得元组类型的定义,或者你到处都会看到烦人的长类型名称.我喜欢元组.我在必要时使用它们.但它通常仅限于几种情况,例如N元素索引或使用多重映射来绑定范围迭代器对.它通常在非常有限的范围内.
与Haskell或Python相比,它看起来非常丑陋和hacky.当C++ 0x到达此处并且我们得到'auto'关键字时,元组将开始变得更具吸引力.
元组的有用性与声明,打包和解包它们所需的击键次数成反比.
对我来说,这是习惯,举手说明:元组并没有为我解决任何新问题,只有少数我已经可以处理好了.交换价值仍然感觉更轻松的老式方法 - 而且,更重要的是,我真的不想想怎么换"更好".它现在已经足够好了.
就个人而言,我认为元组不是返回多个值的好方法 - 听起来像structs 的工作.
但是如果要旋转三个值怎么办?
swap(a,b);
swap(b,c); // I knew those permutation theory lectures would come in handy.
Run Code Online (Sandbox Code Playgroud)
好的,所以使用4个等值,最终n元组变得比n-1互换的代码少.如果您自己实现了一个三周期模板,那么使用默认交换这将完成6个分配,而不是您所拥有的4个分配,尽管我希望编译器能够解决简单类型的问题.
您可以提出交换不实用或不合适的情况,例如:
tie(a,b,c) = make_tuple(b*c,a*c,a*b);
Run Code Online (Sandbox Code Playgroud)
打开包装有点尴尬.
但是,有一些已知的方法可以处理元组有用的最常见情况,因此没有采用元组的紧迫性.如果没有别的,我不相信:
tie(a,b,c) = make_tuple(b,c,a);
Run Code Online (Sandbox Code Playgroud)
不做6份,使它完全不适合某些类型(集合最明显).随意说服我,元组是"大"类型的好主意,说这不是这样的:-)
对于返回多个值,如果值是不兼容的类型,则元组是完美的,但是如果调用者可能以错误的顺序获取它们,则某些人不喜欢它们.有些人根本不喜欢多个返回值,并且不想通过简化它们来鼓励使用它们.有些人更喜欢用于输入和输出参数的命名结构,并且可能无法使用棒球棒来说服使用元组.没有考虑到味道.
正如许多人所指出的那样,元组并不像其他功能那样有用.
交换和旋转的噱头只是噱头.对于那些之前没有看过它们的人来说,它们完全令人困惑,因为它几乎是每个人,这些噱头只是糟糕的软件工程实践.
使用元组返回多个值远不如自我文档那么替代 - 返回命名类型或使用命名引用.如果没有这种自我记录,很容易混淆返回值的顺序,如果它们是可相互转换的,并且不是更明智的.
不是每个人都可以使用增强,而TR1还没有广泛使用.
在嵌入式系统上使用C++时,引入Boost库变得复杂.它们彼此耦合,因此库大小增加.您返回数据结构或使用参数传递而不是元组.在Python中返回元组时,数据结构的顺序和返回值的类型只是不明确.
小智 5
你很少看到它们,因为设计良好的代码通常不需要它们——在野外使用匿名结构优于使用命名结构的情况并不多。由于元组真正代表的是一个匿名结构,因此在大多数情况下,大多数编码人员只会使用真实的东西。
假设我们有一个函数“f”,其中元组返回可能有意义。作为一般规则,这些功能通常足够复杂,以至于它们可能会失败。
如果 "f" CAN 失败,你需要一个状态返回——毕竟,你不希望调用者必须检查每个参数来检测失败。"f" 可能符合模式:
struct ReturnInts ( int y,z; }
bool f(int x, ReturnInts& vals);
int x = 0;
ReturnInts vals;
if(!f(x, vals)) {
..report error..
..error handling/return...
}
Run Code Online (Sandbox Code Playgroud)
这并不漂亮,但看看替代方案有多丑陋。请注意,我仍然需要一个状态值,但代码不再具有可读性,也不会更短。它也可能更慢,因为我承担了 1 个元组副本的成本。
std::tuple<int, int, bool> f(int x);
int x = 0;
std::tuple<int, int, bool> result = f(x); // or "auto result = f(x)"
if(!result.get<2>()) {
... report error, error handling ...
}
Run Code Online (Sandbox Code Playgroud)
另一个显着的缺点隐藏在这里 - 使用“ReturnInts”,我可以通过修改“ReturnInts”而不改变“f”的接口来添加改变“f”的返回。元组解决方案不提供该关键功能,这使其成为任何库代码的次等答案。
| 归档时间: |
|
| 查看次数: |
53042 次 |
| 最近记录: |