2013-02-15 122 views
2

来自Java背景,我想了解C++中的指针/引用。我试图从函数返回一个向量。写作:C++ - 函数返回向量

vector<char*> f(){ 
    vector<char*> vec; 
    return vec; 
} 

将返回向量的副本,是否正确?更好的方法是返回像这样的向量的指针:

vector<char*>* f(){ 
    vector<char*>* vec = new vector<char*>; 
    return vec; 
} 

我是对的吗,还是完全错了?

+0

我不是说它是重复的,但是这个问题很好地讨论了这个问题的各个方面:http://stackoverflow.com/questions/3350385/how-to-return-an-object-in-c – jogojapan 2013-02-15 01:19:07

回答

0

你错了,你不想在C++中做到这一点。几乎每个C++编译器都有称为命名返回值优化的命名返回值优化,这将通过为堆栈上的返回值分配空间来有效地移动vec,而不是复制它,然后基本上“构建” 。这消除了开销。

Wikipedia这篇文章给出了一个合理的概要。

0

我是正确的,还是完全错误?

这是完全错误的,至少在C++ 11中移动语义存在,只要你不需要创建别名返回值(这似乎不被你的情况,即使它是,可能需要使用智能指针而不是原始指针)。

现在按值返回一个向量即可。大多数情况下,即使在C++ 98中,编译器也会将调用复制到复制构造函数(以及C++ 11中的移动构造函数)。这被称为(Named) Return Value Optimization

在C++ 11中,标准库的所有容器都支持移动构造函数,因此,即使未复制或移动时,通过值返回容器也不昂贵。

+0

我说的是前11 – Bober02 2013-02-15 01:05:27

+0

这仍然不是一个问题,即使使用C++ 03代码。 – Yuushi 2013-02-15 01:08:35

1

在C++ 03中,按值返回最有可能导致RVO(返回值优化),从而避免不必要的副本。在C++ 11移动语义将照顾副本。

那么,为什么按价值回报呢?因为它可以防止不必要的对象具有动态生存期您的示例代码也不尊重您的函数的用户可能要使用的任何分配策略。

一般来说,在C++ 11中返回一个容器甚至是一个坏主意:它将用户限制在特定的容器中,因为它不可能跨容器移动,只能复制。标准库通过OutputIteratorS解决了这个问题。你的算法很可能写成:

template<typename OutputIterator> 
OutputIterator f(OutputIterator o); 

这样你就从容器中抽象出来,同时绕开了原来的问题。