c ++ 11最佳参数传递

fsc*_*can 8 c++ parameter-passing rvalue-reference c++11

考虑这些类:

#include <iostream>
#include <string>

class A
{
    std::string test;
public:
    A (std::string t) : test(std::move(t)) {}
    A (const A & other) { *this = other; }
    A (A && other) { *this = std::move(other); }

    A & operator = (const A & other)
    {
        std::cerr<<"copying A"<<std::endl;
        test = other.test;
        return *this;
    }

    A & operator = (A && other)
    {
        std::cerr<<"move A"<<std::endl;
        test = other.test;
        return *this;
    }
};

class B
{
    A a;
public:   
    B (A && a) : a(std::move(a)) {}
    B (A const & a) : a(a) {}
};
Run Code Online (Sandbox Code Playgroud)

在创建a时B,我总是有一个最佳前向路径A,一个是rvalues,一个是lvalues.

是否可以使用一个构造函数实现相同的结果?在这种情况下,这不是一个大问题,但是多个参数呢?我需要参数列表中每个可能出现的左值和右值的组合.

这不仅限于构造函数,还适用于函数参数(例如setter).

注意:这个问题严格来说class B; class A存在只是为了可视化复制/移动调用的执行方式.

How*_*ant 9

"按价值"方法是一种选择.它不像你拥有的那样最优,但只需要一次重载:

class B
{
    A a;
public:   
    B (A _a) : a(move(_a)) {}
};
Run Code Online (Sandbox Code Playgroud)

对于左值和左值,成本是1个额外的移动构造,但这对于prvalues(1个移动)仍然是最佳的."xvalue"是使用std :: move强制转换为右值的左值.

您还可以尝试"完美转发"解决方案:

class B
{
    A a;
public:   
    template <class T,
              class = typename std::enable_if
              <
                 std::is_constructible<A, T>::value
              >::type>
    B (T&& _a) : a(std::forward<T>(_a)) {}
};
Run Code Online (Sandbox Code Playgroud)

这将使您回到最佳的复制/移动结构数.但是你应该约束模板构造函数,使它不是过于通用.您可能更喜欢使用is_convertible而不是is_constructible,就像我上面所做的那样.这也是一个构造函数解决方案,但是当您添加参数时,您的约束变得越来越复杂.

注意:上面需要约束的原因是因为没有,客户端B在查询时会得到错误的答案std::is_constructible<B, their_type>::value.如果没有适当的约束,它将错误地回答为真B.

我想说这些解决方案都不会比其他解决方案更好.这里有工程权衡.