【问题标题】:Does std::for_each pass by value or by reference?std::for_each 是按值传递还是按引用传递?
【发布时间】:2013-07-09 20:25:53
【问题描述】:

我有一个带有一对 std::string 和 Person 指针的测试图

class MyMap {
public:
    void clear() {
       std::for_each(people.begin(), people.end(),std::bind1st(std::mem_fun(&MyMap::remove), this));
    }
    void remove(std::pair<std::string, Person*> p) { delete p.second; }
private:
    std::map<name, Person*> people;
};

我的问题是 for_each 是否通过 ref 或 value 传递每个 Person 对?值得用我自己的吗,这个比较干净。

除此之外,如果我想使用 boost::bind 或 std::bind (c++11) 而不是 bind1st,我该怎么做?这个函数应该像具有继承 std::unary_function 的 operator() 的结构吗?

【问题讨论】:

  • "for_each 通过 ref 或 value 传递每个 Person 对": pass where?如果你在谈论函数(第三个参数),它取决于函数定义的方式。
  • 查看当前功能。 for_each 不接受签名 void remove(std::pair&lt;std::string, Person*&gt;&amp; p) 抱怨超载
  • 为什么重要?你的删除函数所做的就是删除这个人。
  • 如果您可以访问 C++11,而不必为std::bind 烦恼,只需使用基于范围的for 版本。
  • @dev-inside。是的。但是您可能不应该存储指针。 std::unique_ptr?

标签: c++ pass-by-reference pass-by-value stdmap


【解决方案1】:

地图的类型是std::map&lt;name, Person*&gt;,但remove函数的参数是std::pair&lt;std::string, Person*&gt;。除非namestd::string 的typedef,否则这将不起作用。

按照当前定义remove 函数的方式,您将复制mapvalue_type。将函数签名更改为:

void remove(std::pair<const std::string, Person *>& p)
//                    ^^^^^                       ^
//                    key must be const           take a reference

使用std::bind 代替std::bind1st

std::for_each( people.begin(), 
               people.end(), 
               std::bind( &MyMap::remove, this, std::placeholders::_1 ) );

但是如果你可以使用 C++11 的特性,就不需要std::bind,lambda 更好。

std::for_each( people.begin(), 
               people.end(), 
               []( decltype(*people.begin())& p ) { delete p.second; } );

或使用基于范围的 for 循环

for( auto&& p : people ) {
    delete p.second;
}

【讨论】:

    【解决方案2】:

    for_each 将按值或按引用调用函子,具体取决于您定义函子的方式。

    例如:

    struct Gizmo
    {
      bool operator() (const Zippy& rhs) const
      {
        // ...
      }
    };
    

    这个函子是按引用调用的。然而:

    struct Gizmo
    {
      bool operator() (Zippy rhs) const
      {
        // ...
      }
    };
    

    这是按值调用。

    【讨论】:

    • 是的,我知道,但是在 std::for_each 中传递它会导致编译错误:13: required from 'void MyMap::clear()' ../src/main.cc:45:34:从这里需要 /usr/include/c++/4.7/backward/binders.h:125:7: 错误:'typename _Operation::result_type std::binder1st<_operation>::operator()(typename _Operation::second_argument_type&) const [with _Operation = std::mem_fun1_t;类型名 _Operation::result_type = void; typename _Operation::second_argument_type = Person*&]' 不能重载
    • 向我们展示 'Person` 和 name
    猜你喜欢
    • 2016-11-28
    • 2017-11-14
    相关资源
    最近更新 更多