Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 返回值的元组与结构_C++_Tuples_Boost Tuples - Fatal编程技术网

C++ 返回值的元组与结构

C++ 返回值的元组与结构,c++,tuples,boost-tuples,C++,Tuples,Boost Tuples,我正试着了解元组(谢谢@litb),对于它们的使用,通常的建议是对于返回大于1值的函数 这是我通常会使用结构的东西,我不理解在这种情况下元组的优点——对于极端懒惰的人来说,这似乎是一种容易出错的方法 ,我会用这个 struct divide_result { int quotient; int remainder; }; 使用元组,您将 typedef boost::tuple<int, int> divide_result; …这不会让我充满信心 那么,元组比结

我正试着了解元组(谢谢@litb),对于它们的使用,通常的建议是对于返回大于1值的函数

这是我通常会使用结构的东西,我不理解在这种情况下元组的优点——对于极端懒惰的人来说,这似乎是一种容易出错的方法

,我会用这个

struct divide_result {
    int quotient;
    int remainder;
};
使用元组,您将

typedef boost::tuple<int, int> divide_result;
…这不会让我充满信心


那么,元组比结构有哪些优点可以弥补歧义呢?

对于元组,您可以使用
tie
,这有时非常有用:
std::tr1::tie(商,余数)=do_除法()。这对于结构来说并不容易。其次,在使用模板代码时,有时依赖对比为结构类型添加另一个typedef更容易


如果类型不同,那么pair/tuple实际上并不比struct差。例如,考虑
pair readFromFile()
,其中int是读取的字节数,bool是eof是否已命中。在这种情况下添加一个结构对我来说似乎太过分了,尤其是这里没有歧义。

可以防止代码中充斥着许多结构定义。对于编写代码的人和其他使用它的人来说,只记录元组中的每个元素是什么比编写自己的结构/让人们查找结构定义更容易。

元组将更容易编写-无需为每个返回内容的函数创建新的结构。关于去哪里的文档将转到函数文档,这是无论如何都需要的。要使用函数,在任何情况下都需要阅读函数文档,元组将在文档中进行解释。

我100%同意你的观点

要从一个方法返回多个值,除了元组之外,您还有几个选项,哪一个选项最好取决于您的情况:

  • 创建一个新的结构。当您返回的多个值是相关的时,这是很好的,创建一个新的抽象是合适的。例如,我认为“divide_result”是一个很好的通用抽象,传递这个实体比传递一个无名的元组更清晰。然后,您可以创建对该新类型进行操作的方法,将其转换为其他数值类型,等等

  • 使用“Out”参数。通过引用传递多个参数,并通过指定给每个out参数来返回多个值。当您的方法返回几个不相关的信息时,这是合适的。在这种情况下,创建一个新的结构将是过分的,如果没有参数,您将强调这一点,并且每个项都会得到它应得的名称


  • 元组是邪恶的。

    元组在ML或Haskell等语言中非常有用

    在C++中,它们的语法使它们不那么优雅,但在以下情况下可能有用:

    • 您有一个必须返回多个参数的函数,但结果对于调用者和被调用者都是“本地”的;您不希望仅为此定义结构

    • 您可以使用tie函数进行非常有限形式的模式匹配“alaml”,这比出于相同目的使用结构更优雅

    • 它们带有预定义的运算符,可以节省时间

    元组 我想我同意你的观点,即什么样的立场对应于什么样的变量会引起混乱。但我认为有两个方面。一个是呼叫端,另一个是被叫方:

    我认为我们得到了非常清楚的结果,但是如果您必须一次返回更多的值,那么它可能会变得混乱。一旦调用方的程序员查阅了
    div
    的文档,他就会知道位置是什么,并且能够编写有效的代码。根据经验,我建议一次返回的值不要超过4个。对于任何超出此范围的内容,请选择结构

    输出参数 当然,也可以使用输出参数:

    int remainder; 
    int quotient;
    div(10, 3, &quotient, &remainder);
    
    现在我认为这说明了元组比输出参数更好。我们将
    div
    的输入与输出混合,但没有获得任何优势。更糟糕的是,我们让该代码的读者怀疑
    div
    be的实际返回值可能是多少。当输出参数有用时,有一些极好的例子。在我看来,只有在没有其他方法的情况下才应该使用它们,因为返回值已经被接受,不能更改为元组或结构
    operator>
    是使用输出参数的一个很好的例子,因为返回值已经为流保留,所以您可以链接
    operator>
    调用。如果您不需要使用运算符,而且上下文也不是非常清楚,我建议您使用指针,在调用端发出信号,表示对象实际上被用作输出参数,并在适当的情况下添加注释

    返回结构 第三个选项是使用结构:

    div_result d = div(10, 3);
    
    我认为它肯定会因为清晰而获奖。但是请注意,您仍然需要访问该结构中的结果,并且结果不会“暴露”在表中,因为输出参数和与
    tie
    一起使用的元组就是这样

    我认为这些天的一个要点是尽可能使所有的东西都通用。假设你有一个可以打印元组的函数。你可以这么做

    cout << div(10, 3);
    

    cout我倾向于将元组与typedef结合使用,以至少部分缓解“无名元组”问题。例如,如果我有一个网格结构,那么:

    //row is element 0 column is element 1
    typedef boost::tuple<int,int> grid_index;
    
    这是一个有点做作的例子,但我认为大多数时候它在可读性、明确性和易用性之间找到了一个令人满意的中间点

    或者在你的例子中:

    //quotient is element 0 remainder is element 1
    typedef boost:tuple<int,int> div_result;
    div_result div(int dividend,int divisor);
    
    //商是元素0,余数是元素1
    typedef boost:tuple div_结果
    
    //row is element 0 column is element 1
    typedef boost::tuple<int,int> grid_index;
    
    grid_index find(const grid& g, int value);
    
    //quotient is element 0 remainder is element 1
    typedef boost:tuple<int,int> div_result;
    div_result div(int dividend,int divisor);
    
    struct quotient;
    struct remainder;
    
    using boost::fusion::map;
    using boost::fusion::pair;
    
    typedef map<
        pair< quotient, int >,
        pair< remainder, int >
    > div_result;
    
    using boost::fusion::at_key;
    
    res = div(x, y);
    int q = at_key<quotient>(res);
    int r = at_key<remainder>(res);
    
    struct A
    {
      int a;
      int b;
    };
    
    void foo (A const & a)
    {
      // ...
    }
    
    void bar ()
    {
       A dummy = { 1, 2 };
       foo (dummy);
    }
    
    struct A
    {
      int a;
      int b;
      int c;
    };
    
    typedef boost::tuple<int, int, int> Tuple;
    enum {
      A
      , B
      , C
    };
    
    void foo (Tuple const & p) {
    }
    
    void bar ()
    {
      foo (boost::make_tuple (1, 2));  // Compile error
    }
    
    void incrementValues (boost::tuples::null_type) {}
    
    template <typename Tuple_>
    void incrementValues (Tuple_ & tuple) {
       // ...
       ++tuple.get_head ();
       incrementValues (tuple.get_tail ());
    }