【问题标题】:How to use boost lambda to populate a vector of pointers with new objects如何使用 boost lambda 用新对象填充指针向量
【发布时间】:2010-01-11 16:20:26
【问题描述】:

我最近开始使用 boost lambda,并认为我会尝试在它将/应该使事情更容易阅读的地方使用它。

我有一些类似于以下的代码

std::vector< X * > v;
for ( int i = 0 ; i < 20 ; ++i )
    v.push_back( new X() );

稍后,删除它...

std::for_each( v.begin(), v.end(), boost::lamda::delete_ptr() );

整理得很整齐。

但是,我想我应该尝试使用 lambda 对向量的总体进行“lambda-ising”...然后烟花就开始了...

我试过了..

std::generate_n( v.begin(), 20, _1 = new X() );

但这会引发各种编译器错误。

实现这一目标的最佳“lambda”方式的任何想法。

谢谢 标记。

【问题讨论】:

  • 一般情况下,不要将动态分配的指针存储在向量中——你的代码不是异常安全的,如果 X 的构造函数失败会泄漏内存。
  • 嗨,乔,我有兴趣对此进行扩展。我不确定 X 的构造函数如何失败并泄漏内存。我认为 C++ 标准说 new 在遇到异常时会返回 null 并在重新抛出异常之前清理内存。当然我可能完全错了。
  • @ScaryAardvark。如果内存不足,New 会抛出 std::bad_alloc - 除非您使用非抛出形式,否则它永远不会返回 null。
  • 至于内存泄漏,我有点错误——如果 'new X()' 抛出,你的代码不会泄漏,如果 v.push_back() 抛出它就会泄漏。

标签: c++ stl boost lambda containers


【解决方案1】:

这里有一个代码 sn-p 可以满足你的要求:

#include <algorithm>
#include <vector>

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/construct.hpp>

typedef int X;

int main() {
  std::vector<X*> v;
  std::generate_n( std::back_inserter(v), 20, boost::lambda::new_ptr<X>() );
  std::for_each( v.begin(), v.end(), boost::lambda::delete_ptr() );
}

您可能需要考虑使用 boost::ptr_vector,因为以异常安全的方式使用带有动态分配指针的 std::vector 并不容易。

【讨论】:

  • 如果你想实现这一点,你可以在 generate_n 调用前添加一个 v.reserve(20)。
【解决方案2】:

你可以考虑:

static const int PtrVectorSize = 20;

// ....
v.resize(PtrVectorSize);
generate_n(v.begin(), PtrVectorSize, new_ptr<X>());

另外,您可以使用 boost::ptr_vector 并保存自己的删除。

【讨论】:

  • 是的,这当然更清晰。我喜欢你通过调整大小来摆脱 back_inserter 的方式..
  • 在填充生成之前进行保留或调整大小很可能更有效,但对于已知大小的序列,我通常更喜欢调整大小/迭代器而不是 Reserve/back_inserter我想第二个可以被认为是特殊意义上的“更安全”。
【解决方案3】:

无法帮助您使用 lambda,但您看过 boost::assign 库吗?

【讨论】:

    【解决方案4】:

    好的,经过一番额外的游戏,我想出了这个......

    std::generate_n( std::back_insert_iterator< std::vector< X* > >( ip ), 20, new_ptr< X >() ) );
    

    我不太确定这是否优雅。从编程的角度来看,可能是这样,但从“在 6 个月内我会知道这是什么意思”的角度来看,我不确定......

    请随时指出更好的方法。

    【讨论】:

    • 至少 std::back_inserter(v) 使它更具可读性。
    • std::back_inserter 的模板目标是类型而不是实例,所以不幸的是它必须是 std::vector,而不是 v
    • back_inserter 是一个函数,因此它可以自动推断出模板参数 - 请参阅下面的答案。
    • 啊。对不起,我错过了它是一个功能的事实。好想法:o)
    猜你喜欢
    • 2016-04-22
    • 1970-01-01
    • 1970-01-01
    • 2011-02-11
    • 1970-01-01
    • 1970-01-01
    • 2018-11-03
    • 1970-01-01
    • 2019-12-19
    相关资源
    最近更新 更多