来自Java背景,我试图理解C ++中的指针/引用。我试图从函数返回一个向量。写作:
vector<char*> f(){
vector<char*> vec;
return vec;
}
会返回向量的副本,对吗?更好的方法是返回一个指向vector的指针,如下所示:
vector<char*>* f(){
vector<char*>* vec = new vector<char*>;
return vec;
}
我是正确的,还是完全错了?
答案 0 :(得分:1)
在C ++ 03中,按值返回最有可能导致RVO(返回值优化),这将消除不必要的副本。在C ++ 11中,移动语义将处理副本。
那么,为什么首先按价值回报呢?因为它可以防止不必要的物体具有动态寿命。您的示例代码也不尊重您的函数用户可能想要使用的任何分配策略。
一般来说,返回一个容器即使在C ++ 11中也是一个坏主意:它将用户限制在该特定容器中,因为它不可能跨容器移动,只能复制。标准库使用OutputIteratorS
解决了这个问题。您的算法最有可能写成:
template<typename OutputIterator>
OutputIterator f(OutputIterator o);
这样你就可以从容器中抽象出来并避开原来的问题。
答案 1 :(得分:0)
你错了,你不想在C ++中这样做。几乎每个C ++编译器都有所谓的命名返回值优化,它将(有效地)通过为堆栈上的返回值分配空间来移动而不是复制vec
,然后基本构建“到位”。这消除了开销。
关于此的Wikipedia文章提供了合理的纲要。
答案 2 :(得分:0)
我是正确的,还是完全错了?
这是完全错误的,至少在C ++ 11中存在移动语义,并且只要您不需要创建返回值的别名 (这似乎不是你的情况,即使它是,可能需要使用智能指针而不是原始指针)。
按值返回向量现在可以。大多数情况下,即使在C ++ 98中,编译器也会忽略对复制构造函数的调用(以及C ++ 11中的移动构造函数)。这称为(Named) Return Value Optimization。
在C ++ 11中,标准库的所有容器都支持移动构造函数,因此即使没有省略复制或移动,按值返回容器并不昂贵。