微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C为什么将左值传递给移动构造函数适用于模板?

我有这个代码,它不编译,这是预期的.

这是错误:rvalue引用不能绑定到左值

class SomeData
{
public:
    vector<int> data;

    SomeData()
    {
        cout << "SomeData ctor" << endl;
        data.push_back(1);
        data.push_back(2);
        data.push_back(3);
    }

    SomeData(const SomeData &other)
    {
        cout << "SomeData copy ctor" << endl;
        data = other.data;
    }

    SomeData(SomeData &&other)
    {
        cout << "SomeData move ctor" << endl;
        data = move(other.data);
    }

    ~SomeData()
    {
        cout << "SomeData dtor" << endl;
    }

    void Print() const
    {
        for(int i : data)
            cout << i;

        cout << endl;
    }
};

void Function(SomeData &&someData)
{
    SomeData localData(someData);
    localData.Print();
}

int main(int argc,char *argv[])
{
    SomeData data;
    Function(data);                       // ERROR

    data.Print();

    return 0;
}

但是,当我将Function()转换为模板时,它工作正常,并使用SomeData的复制构造函数.

template<class T>
void Function(T &&someData)
{
    T localData(someData);                  // no more error
    localData.Print();
}

这是标准的C行为吗?

我注意到视觉工作室在模板方面往往更宽容,所以我想知道是否可以从所有兼容的C 11编译器中获得相同的行为.

解决方法

是.在模板函数的情况下,编译器推导出模板参数T,使其与给定的参数匹配.

由于someData实际上是一个左值,因此T被推导为SomeData&amp ;.然后,在类型推断之后,函数的声明变为

void Function(SomeData & &&)

和SomeData& &&,跟随rules for reference collapsing,成为SomeData&.

因此,函数参数someData变为左值引用,并且这样传递给localData的初始化.注意(正如@aschepler正确指出的那样)localData被声明为T,所以它本身就是SomeData&类型的引用.因此,这里没有复制构造 – 只是初始化引用.

如果您希望localData是实际副本,则必须从SomeData&中转换类型.进入SomeData,即你必须删除&从类型.你可以使用std :: remove_reference来做到这一点:

template<class T>
void Function(T &&someData)
{
   /* Create a copy,rather than initialize a reference: */
    typename std::remove_reference<T>::type localData(someData);
    localData.Print();
}

(为此,你必须#include< type_traits&gt ;.)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐