c++11 使用 std::map 作为返回值

Posted

技术标签:

【中文标题】c++11 使用 std::map 作为返回值【英文标题】:c++11 use std::map as return value 【发布时间】:2021-11-15 13:34:34 【问题描述】:

我通常返回 std::vector 或 std::map 的对象作为传入的参考参数(如下面的 funcVec2 和 funcMap2)。但是写代码的时候有点不方便。所以我想如果我可以在c ++ 11下使用返回值(如下面的funcVec1和funcMap1),因为它会调用移动构造函数而不是复制构造函数,所以它可能仍然只花费一个构造时间并且没有解构作为传入引用的形式参数。 但是我编写了下面的代码来验证它,结果发现 funcVec1 和 funcMap1 比 funcVec2 和 funcMap2 需要更多的时间。所以我现在很困惑,为什么 funcVec1 和 funcMap1 需要这么长时间?

#include <iostream>
#include <vector>
#include <map>
#include <chrono>
using namespace std;
vector<int> funcVec1() 
    vector<int >vec;
    for (int i = 0; i < 10; ++i) 
        vec.push_back(i);
    
    return vec;


void funcVec2(vector<int>&vec) 
    for (int i = 0; i < 10; ++i) 
        vec.push_back(i);
    
    return;


map<int, int> funcMap1() 
    map<int, int>tmpMap;
    for (int i = 0; i < 10; ++i) 
        tmpMap[i] = i;
    
    return tmpMap;


void funcMap2(map<int, int>&tmpMap) 
    for (int i = 0; i < 10; ++i) 
        tmpMap[i] = i;
    


int main()

    using namespace std::chrono;
    system_clock::time_point t1 = system_clock::now();
    for (int i = 0; i < 100000; ++i) 
        vector<int> vec1 = funcVec1();
    
    auto t2 = std::chrono::system_clock::now();
    cout << "return vec takes " << (t2 - t1).count() << " tick count" << endl;
    cout << duration_cast<milliseconds>(t2 - t1).count() << " milliseconds" << endl;
    cout << " --------------------------------" << endl;
    vector<int> vec2;
    for (int i = 0; i < 100000; ++i) 
        funcVec2(vec2);
    
    auto t3 = system_clock::now();
    cout << "reference vec takes " << (t3 - t2).count() << " tick count" << endl;
    cout << duration_cast<milliseconds>(t3 - t2).count() << " milliseconds" << endl;
    cout << " --------------------------------" << endl;
    for (int i = 0; i < 100000; ++i) 
        map<int, int> tmpMap1 = funcMap1();
    
    auto t4 = system_clock::now();
    cout << "return map takes " << (t4 - t3).count() << " tick count" << endl;
    cout << duration_cast<milliseconds>(t4 - t3).count() << " milliseconds" << endl;
    cout << " --------------------------------" << endl;
    map<int, int>tmpMap2;
    for (int i = 0; i < 100000; ++i) 
        funcMap2(tmpMap2);
    
    auto t5 = system_clock::now();
    cout << "reference map takes " << (t5 - t4).count() << " tick count" << endl;
    cout << duration_cast<milliseconds>(t5 - t4).count() << " milliseconds" << endl;
    cout << " --------------------------------" << endl;
    return 0;

【问题讨论】:

我没有玩过代码,但我猜这是因为快速示例只是将数据添加到单个向量/映射,而慢速示例为每个调用分配新的向量/映射。每次分配新容器时,内存分配的次数应该多得多。 通常的问题需要问。有没有开启优化?您使用的是什么编译器和标志? 只是一个带有 vs2017 的新控制台项目,没有任何其他额外的优化@Retired Ninja 【参考方案1】:

    您不仅要衡量您的操作时间,还包括打印输出。这是次优的。

    您应该在发布模式下衡量性能。请注意,您没有对对象做任何有用的事情,优化器可能会丢弃您想要测量的大部分代码。

    比较不“公平”。例如,在您的 map1 案例中,您正在构建一个空地图,填充它(内存分配发生在这里),然后你把它扔掉。在 map2 的情况下,您一遍又一遍地重用相同的地图对象。您不会一遍又一遍地分配内存。

【讨论】:

以上是关于c++11 使用 std::map 作为返回值的主要内容,如果未能解决你的问题,请参考以下文章

std::map的insert和下标[]操作区别

使用类方法插入 std::map

在编译时查找 std::map 的重复值

计算向量的 std::map 的值作为键并作为值的两倍?

什么时候可以返回 NULL 作为 C 函数的返回值?

QMap 和map哪个效率高?