【问题标题】:Why does the C++ standard not prohibit such a dreadful usage?为什么 C++ 标准不禁止这种可怕的用法?
【发布时间】:2011-05-18 09:18:20
【问题描述】:

源代码非常简单,不言而喻。该问题包含在评论中。

#include <iostream>
#include <functional>

using namespace std;
using namespace std::tr1;

struct A
{
    A()
    {
        cout << "A::ctor" << endl;
    }

    ~A()
    {
        cout << "A::dtor" << endl;
    }

    void foo()
    {}
};

int main()
{
    A a;
    /*
    Performance penalty!!!

    The following line will implicitly call A::dtor SIX times!!! (VC++ 2010)    
    */
    bind(&A::foo, a)();  

    /*
    The following line doesn't call A::dtor.

    It is obvious that: when binding a member function, passing a pointer as its first 
    argument is (almost) always the best way. 

    Now, the problem is: 

    Why does the C++ standard not prohibit bind(&SomeClass::SomeMemberFunc, arg1, ...) 
    from taking arg1 by value? If so, the above bind(&A::foo, a)(); wouldn't be
    compiled, which is just we want.
    */
    bind(&A::foo, &a)(); 

    return 0;
}

【问题讨论】:

  • 记住还有第三种选择:bind(&amp;A::foo, std::ref(a))();
  • @icecrime:我知道。但我只是想知道为什么 C++ 标准没有明确禁止这种可怕而无用的用法?
  • 从实现的角度来看,有几个重载的绑定函数,其中一个通过值获取它的第一个参数。如果实现不提供这样的重载功能。那么目标就很容易实现了。

标签: c++11 bind pass-by-value


【解决方案1】:

首先,您的代码还有第三种选择:

bind(&A::foo, std::ref(a))(); 

现在,为什么默认复制参数?我认为,但这只是一个疯狂的猜测,认为bind 默认行为独立于参数生存期被认为是可取的:绑定的结果是一个函子,其调用可能在参数销毁后很长时间被延迟。

您是否希望从以下代码中默认生成 UB

void foo(int i) { /* ... */ }

int main()
{
    std::function<void ()> f;

    {
        int i = 0;
        f = std::bind(foo, i);
    }

    f(); // Boom ?
}

【讨论】:

  • 非常感谢您令人信服的“疯狂猜测”。
【解决方案2】:

C++ 的使命不是让编写慢代码变得不可能,甚至更难。这只是要求您明确要求花里胡哨。

【讨论】:

  • 让错误使用变得更加困难通常被认为是好的设计
  • 真;但是很多人很难相信 C++ 是设计好的,更不用说设计得好 ;)
  • 好吧,那些人是无知的。 C++ 两者兼而有之。它只是在一些不寻常的约束下设计的,这需要一些非常尴尬的权衡。但是(几乎)C++ 中的每一个缺点和奇怪的权衡都是有原因的
猜你喜欢
  • 1970-01-01
  • 2016-09-05
  • 2021-04-26
  • 1970-01-01
  • 2020-04-07
  • 2011-05-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多