基于函数返回的stl容器的构造效率

Efficiency of construction of stl container based on a function return

本文关键字:stl 效率 返回 于函数 函数      更新时间:2023-10-16

我有一个返回stl容器的工厂函数:

const std::vector<int> f(...) {
    std::vector<int> retval;
    return retval;
}

我想这是ok的定义一个stl实例如下(没有错误):

const std::vector<int> stl_instance(f(...));

但是这样做有效率吗?

临时stl对象是否直接赋值给stl_instance ?

返回const右值是c++ 11中的反模式。首先考虑返回非const右值:

std::vector<int> f(int n) 
{ 
    return std::vector<int>(n); 
}
int main() 
{ 
    std::vector<int> v; 
    v = f(3); 
} 

在c++ 98/03中,这段代码将至少两次进入堆:

  1. 在f内部创建向量(如果RVO适用)
  2. 将f的返回值赋值给v

如果你的编译器不应用RVO,你会得到3个堆分配。

在c++ 11中,你只得到一个堆分配:在f中创建向量。这与RVO无关。原因是所有STL容器都有带有

签名的move构造函数和move赋值操作符。
vector( vector&& other );
vector& operator=( vector&& other );

右值引用&&将把资源从你的创建函数内部直接移动到它们的目的地。但是,您的代码具有签名

const std::vector<int> f(int n) 
{ 
    return std::vector<int>(n); 
}

将禁用move语义,因为T&&(即移动构造函数和赋值操作符的参数)不会绑定到const右值形参(即函数的返回值)。这有效地使您的代码运行在c++ 98/03下(即2或3堆分配)。

这是良好的和合法的代码。
编译器将通过拷贝省略处理必要的优化(如果可以的话)。

保证临时f(...)至少在表达式结束之前有效。注意,表达式结束于stl_instance(f(...))的返回值之后,确切地说是; ( call结尾的分号)。所以它是完全有效的。

c++ 03 Standard§12.2/3:

临时对象在(词法上)包含创建它们的点的完整表达式(1.9)求值的最后一步被销毁。