Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.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++;_C++_Design Patterns - Fatal编程技术网

C++ 函数返回C++;

C++ 函数返回C++;,c++,design-patterns,C++,Design Patterns,在我当前的项目中,我需要实现相当多的函数/方法,这些函数/方法接受一些参数并生成一组结果(相当大)。因此,为了在不复制的情况下返回此集合,我可以创建新集合并返回智能指针: boost::shared_ptr<std::vector<Stuff> > generate(); boost::shared_ptr generate(); 或引用将填充的向量: void generate(std::vector<Stuff> &output); void

在我当前的项目中,我需要实现相当多的函数/方法,这些函数/方法接受一些参数并生成一组结果(相当大)。因此,为了在不复制的情况下返回此集合,我可以创建新集合并返回智能指针:

boost::shared_ptr<std::vector<Stuff> > generate();
boost::shared_ptr generate();
或引用将填充的向量:

void generate(std::vector<Stuff> &output);
void生成(标准::向量和输出);
这两种方法都有好处。第一个清楚地表明向量是函数的输出,在并行化场景中使用它很简单,等等。第二个在循环中调用时可能更有效(因为我们不会每次都分配内存),但是参数是输出并不明显,有人需要清理向量中的旧数据

在现实生活中,哪一种更习惯(即,最佳实践是什么)?在C/J/java中,我会说第一个C++中的什么情况? 另外,是否可以使用C++11有效地按值返回向量?陷阱是什么?

先做正确性检查,然后在必要时进行优化

由于移动语义和返回值优化共同使普通函数结果不可复制,您可能必须对其进行操作,以使其效率足够低,从而值得进行优化


因此,只需将集合作为函数结果返回,然后测量如果您觉得它太慢

您应该按值返回。

使用C++11是否可以有效地按值返回向量

是的,C++11支持。您返回一个值,但编译器知道它是临时的,因此可以调用一个特殊的构造函数(move构造函数),该构造函数专门用于“窃取”返回对象的内部。毕竟,你不会再使用那个临时对象了,既然你可以移动它的内容,为什么还要复制它呢

除此之外,值得一提的是,大多数C++编译器,甚至是前C ++ 11,都实现了,这将无论如何都避免拷贝,不会导致开销。因此,您可能希望在优化之前实际测量(可能)得到的性能损失


我认为您应该只在需要时通过引用传递,或者返回共享指针。这似乎不是你的情况。

有另一种方法。如果可以将函数设置为模板,请将输出迭代器(其类型为模板参数)设置为参数:

tempalte<class OutputIterator>
void your_algorithm(OutputIterator out) {
    for(/*condition*/) {
        ++out = /* calculation */;
    }
}
tempalte
作废您的_算法(OutputIterator out){
对于(/*条件*/){
++out=/*计算*/;
}
}

这样做的好处是,调用者可以决定将结果存储在哪种类型的集合中(例如,输出迭代器可以直接写入文件,或者将结果存储在std::vector中,或者对其进行过滤等等)。

最佳做法可能会让您感到惊讶。我建议在C++03和C++11中都按值返回

  • 在C++03中,如果创建一个
    std::vector
    本地
    generate
    并返回它,编译器可能会删除该副本(几乎肯定会删除)。参见C++03§12.8/15:

    在具有类返回类型的函数中的return语句中,当表达式是与函数返回类型具有相同类型的非易失性自动对象的名称时,可以通过将自动对象直接构造到函数的返回值中来省略复制操作

  • 在C++11中,如果创建一个
    std::vector
    local以
    generate
    并返回它,那么该副本将首先被视为一个移动(这将非常快),然后可能会被省略(几乎肯定会)。见C++11§12.8/31:

    在具有类返回类型的函数中的return语句中,当表达式是与函数返回类型具有相同cv非限定类型的非易失性自动对象(函数或catch子句参数除外)的名称时,通过将自动对象直接构造到函数的返回值中,可以省略复制/移动操作

    和§12.8/32:

    当满足或将满足省略复制操作的条件时,除非源对象是函数参数,并且要复制的对象由左值指定,否则将首先执行重载解析以选择复制的构造函数,就像对象由右值指定一样


所以按值返回

信不信由你,我建议你不要采用这两种方法中的任何一种,而是采用显而易见的实现并按值返回!编译器通常能够优化掉可能产生的概念副本,将其完全删除。通过以最明显的方式编写代码,您可以让未来的维护人员非常清楚其意图

但是假设您尝试按值返回,而您的程序运行得太慢,让我们进一步假设您的分析器显示按值返回实际上是您的瓶颈。在这种情况下,我将在堆上分配容器,并在C++03中以
自动\u ptr
或在C++11中以
唯一\u ptr
的形式返回,以清楚地表明所有权正在转移,并且generate没有保留该
共享\u ptr
的副本以供以后使用


最后,at系列文章为几乎完全相同的问题提供了一个很好的视角。

请注意,如果向函数传递一个可写引用,很明显函数将向其写入,并且它是一个输出。否则,它将是一个常量引用。你是说
wtf omg(){wtf it;return it;}
将调用move-ctor吗?@nurettin:如果它有一个,是的。否则,它将调用copyctor。但最有可能的是,它不会给他们打电话,因为它会给elid打电话