effective stl 第30条:确保目标区间足够大

本文详细介绍了C++标准模板库STL中transform函数的使用方法,包括如何正确地指定目标区间,如何利用back_inserter等迭代器插入元素,以及如何避免常见的错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>

using namespace std;

int transmogrify(int x)//根据x的值生成新的值
{
    return x + 2;
}

int main()
{
    vector<int> values;
    for (int i = 1; i <= 5; i++)
    {
        values.push_back(i);//将结果加在values的末尾
    }

    vector<int> results;
    //通过transmpgrify函数将values中的全部元素追加到results的末尾
    transform(values.begin(), values.end(), results.end(), transmogrify);
    return 0;
}

上边这段代码虽然能编译通过,但是却不能运行,因为result.end()中没有对象,(result.end()+1)中更没有对象,*(result.begin())中也没有对象,这个代码将导致对无效对象的赋值操作。

可以调用back_inserter,该函数返回的迭代器使得push_back被调用,所以back_inserter适用于所有能提供push_back()方法的容器(vector/string/deque/list都行)

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>

using namespace std;

int transmogrify(int x)//根据x的值生成新的值
{
    return x + 2;
}

int main()
{
    vector<int> values;
    for (int i = 1; i <= 5; i++)
    {
        values.push_back(i);//将结果加在values的末尾
    }

    vector<int> results;
    //通过transmpgrify函数将values中的全部元素追加到results的末尾
    transform(values.begin(), values.end(), back_inserter(results), transmogrify);

    return 0;
}

同样课使用front_inserter,但是仅仅适用于提供该函数的容器,如deque/list

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<list>

using namespace std;

int transmogrify(int x)//根据x的值生成新的值
{
    return x + 2;
}

int main()
{
    list<int> values;
    for (int i = 1; i <= 5; i++)
    {
        values.push_back(i);//将结果加在values的末尾
    }

    list<int> results;
    //通过transmpgrify函数将values中的全部元素追加到results的末尾
    transform(values.begin(), values.end(), front_inserter(results), transmogrify);

    return 0;
}

如果想让transform将输出结果存放在results的前端,同时保留它们在values中原有的顺序,那么只需要俺相反的顺序来遍历values即可。

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<list>

using namespace std;

int transmogrify(int x)//根据x的值生成新的值
{
    return x + 2;
}

int main()
{
    list<int> values;
    for (int i = 1; i <= 5; i++)
    {
        values.push_back(i);//将结果加在values的末尾
    }

    list<int> results;
    //通过transmpgrify函数将values中的全部元素追加到results的末尾
    transform(values.rbegin(), values.rend(), front_inserter(results), transmogrify);

    return 0;
}

inserter将用于把结果插入到容器的任何位置。

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<list>

using namespace std;

int transmogrify(int x)//根据x的值生成新的值
{
    return x + 2;
}

int main()
{
    vector<int> values;
    for (int i = 1; i <= 5; i++)
    {
        values.push_back(i);//将结果加在values的末尾
    }

    vector<int> results;
    //通过transmpgrify函数将values中的全部元素逐个加入results的中间
    int len = results.size() / 2;
    transform(values.begin(), values.end(), inserter(results, results.begin() + len), transmogrify);

    return 0;
}

如果容器时vector或者是string,可以提前使用reserve,预留空间,从而提高插入操作的性能。

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<list>

using namespace std;

int transmogrify(int x)//根据x的值生成新的值
{
    return x + 2;
}

int main()
{
    vector<int> values;
    for (int i = 1; i <= 5; i++)
    {
        values.push_back(i);//将结果加在values的末尾
    }

    vector<int> results;
    results.reserve(results.size() + values.size());//在results中为values预留空间
    //通过transmpgrify函数将values中的全部元素逐个加入results的中间
    int len = results.size() / 2;
    transform(values.begin(), values.end(), inserter(results, results.begin() + len), transmogrify);
    //同上,但这次results不需要重新分配内存空间
    return 0;
}

但是当使用reserve提高一序列连续插入的效率的时候,切记reserve只是增加了容器的容量,而容器的大小并未改变。

因此下边的代码仍然是错的

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<list>

using namespace std;

int transmogrify(int x)//根据x的值生成新的值
{
    return x + 2;
}

int main()
{
    vector<int> values;
    for (int i = 1; i <= 5; i++)
    {
        values.push_back(i);//将结果加在values的末尾
    }
    vector<int> results;
    results.reserve(results.size() + values.size());//在results中为values预留空间
    //通过transmpgrify函数将values中的全部元素逐个加入results的中间
    int len = results.size() / 2;
    transform(values.begin(), values.end(), results.end(), transmogrify);
    //同上,但这次results不需要重新分配内存空间
    return 0;
}

这里写图片描述

改成下边的这样就能解决上述问题:

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<list>

using namespace std;

int transmogrify(int x)//根据x的值生成新的值
{
    return x + 2;
}

int main()
{
    vector<int> values;
    for (int i = 1; i <= 5; i++)
    {
        values.push_back(i);//将结果加在values的末尾
    }
    vector<int> results;
    results.reserve(results.size() + values.size());//在results中为values预留空间
    //通过transmpgrify函数将values中的全部元素逐个加入results的中间
    int len = results.size() / 2;
    transform(values.begin(), values.end(), back_inserter(results), transmogrify);
    //同上,但这次results不需要重新分配内存空间
    return 0;
}

如果只是想简单的覆盖容器中原本的元素,那么久需要确保results中至少有的元素和values一样多,可以使用下边的代码:

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<list>

using namespace std;

int transmogrify(int x)//根据x的值生成新的值
{
    return x + 2;
}

int main()
{
    vector<int> values;
    for (int i = 1; i <= 5; i++)
    {
        values.push_back(i);//将结果加在values的末尾
    }
    vector<int> results;
    if (results.size() < values.size())
    {
        results.resize(values.size());
    }
    transform(values.begin(), values.end(), results.begin(), transmogrify);
    //同上,但这次results不需要重新分配内存空间
    return 0;
}

或者,可以先清空results,然后再resultd的末尾插入:

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<list>

using namespace std;

int transmogrify(int x)//根据x的值生成新的值
{
    return x + 2;
}

int main()
{
    vector<int> values;
    for (int i = 1; i <= 5; i++)
    {
        values.push_back(i);//将结果加在values的末尾
    }
    vector<int> results;
    results.clear();//清空results
    results.reserve(values.size());
    transform(values.begin(), values.end(), back_inserter(results), transmogrify);
    //同上,但这次results不需要重新分配内存空间
    return 0;
}

本条款论证了这个主题的很多变化,但我希望你能牢牢记住本质。无论何时你使用一个要求指定目的区间的算法,确保目的区间已经足够大或者在算法执行时可以增加大小。如果你选择增加大小,就使用插入迭代器,比如ostream_iterators或从back_inserter、front_inserter或inserter返回的迭代器。这是所有你需要记住的东西。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值