2015-09-09 50 views
3

我是编程新手,我正在使用本书研究C++编程语言:编程原理和使用C++的练习。我今天来到这里,因为在第8章的结尾,笔者着重功能,提出了一种锻炼邀请学生去思考更好的解决一个问题:从函数返回值:参考vs结构

编写发现功能的最小矢量参数的最大元素,并计算均值和中值。不要使用全局变量。返回一个包含结果的struct或通过引用参数传递它们。你更喜欢哪一个返回几个值?为什么?

现在,通常我不会定义一个函数来执行多个动作,但在这种情况下,我必须创建一个函数并考虑如何返回多个值。我的第一个方法是创建一个函数,引用参数是这样的:

void my_func(
    vector<double>& numbers, 
    double& min, 
    double& max, 
    double& mean, 
    double& median 
); 

但随着写程序怎么回事,我开始认为这个解决方案中使用的参数太多,也许提出了另一种解决方案(使用struct)会更好。你将如何使用struct来解决这个问题?你如何从函数中返回多个值?

+0

您不会从函数返回多个值,这是不可能的。相反,您返回*一个*结构实例,其中包含多个成员(例如'min','max'等成员)。 –

+0

只要有用和可能,请使用[封装](https://en.wikipedia.org/wiki/Encapsulation_(computer_programming))。在这里它是可能的和有用的,因此你应该在答案中使用一个结构(例如stats)。 – HelloWorld

+1

如果你正在使用C++ 11,你可能想看看[std :: tuple](http://en.cppreference.com/w/cpp/utility/tuple) –

回答

5

使用struct这个问题很简单:定义的返回类型为struct,并使用它,就像这样:

struct stats { 
    double min; 
    double max; 
    double mean; 
    double median; 
}; 
stats my_func(vector<double>& numbers) { 
    stats res; 
    ... 
    res.min = ... 
    res.max = ... 
    res.mean = ... 
    res.median = ... 
    return res; 
} 

这里的代价是,以换取有一个更简单的函数签名时,你的函数的用户需要逐一提取他们想要的元素。

但是,如果结构非常复杂并且复制成本变得过于昂贵,怎么办?

与您的函数的“有效负载”CPU时间相比,复制所需的极端大小的结构变得过于昂贵。最重要的是,C++优化器通过采用copy elisionreturn value optimization策略,当你这样做减少了复制费用:

stats s = my_func(numbers); 

struct变得如此巨大,你不想复制,结合像这两种方法这样的:

void my_func(vector<double>& numbers, stats& res); 
+0

@PoojaNilangekar谢谢,它是一个很好的编辑。不幸的是,它自动被拒绝了,因为我自己正在编辑答案。感谢您收到此复制粘贴错误! – dasblinkenlight

+0

从我学习的基础知识中知道,当函数返回值时,会创建一个return_value的副本。但是如果结构非常复杂并且复制的成本变得太高,那么呢? –

+1

@pieroborrelli随着移动语义和复制的机会是好的,你不会真的做一个副本。特别是如果你从函数返回初始化一个变量。 – NathanOliver

0

声明struct

struct stats { 
    double min; 
    double max; 
    double mean; 
    double median; 
}; 

然后

stats my_func(vector<double>& numbers); 

功能会是这样

stats my_func(vector<double>& numbers) { 
    stats return_value; 

    // Fill in the structure 

    return return_value; 
} 
0

那么你只返回一个结构。

struct res { 
    double min; 
    double max; 
    double mean; 
    double median; 
}; 

res my_func(vector<double>& numbers) { 
    res result; 
    // do stuff, put result in in result.min etc 

    return result; 
} 

其它可以以类似的方式来完成:

void my_func(vector<double>& numbers, 
      res& result) 
{ 
    // the same code except no return value 

    return; 
} 

现在在你的任务的问题(我不回答 - 因为它是你喜欢什么问题),我想提到技术差异是什么。

当返回一个结构就意味着你可能会创建result结构的临时副本(也可能导致两个对象res一个呼叫者和一个my_func一起工作)。而另一种方法意味着你传递给函数基本上决定了结果的放置位置。有了“好”的实现,你可能会得到相同的代码。

+0

随着移动语义和复制的机会是好的,你不会真的做一个副本。特别是如果你从函数返回初始化一个变量。 – NathanOliver

+0

这个可能性已经发生了变化,我改变了它的形式“可能”到“可能”,以表明它现在不太可能。 – skyking