移动构造函数和char数组参数

时间:2013-03-26 16:04:45

标签: c++ visual-c++ c++11 move move-semantics

struct Foo
{
    char data[100];

    template<int T>
    Foo(char (&&var)[T])
    {
        data = std::move(var);
        var = 0;
    } 
};

int main()
{ 
    char v[100];
    //..init v
    Foo f( std::move(v) );   //error C2664: 'Foo::Foo<100>(char (&&)[100])' : cannot convert parameter 1 from 'char [100]' to 'char (&&)[100]'
    return 0;
} 

我不明白为什么MSVC对行Foo f( std::move(v) )不满意? (也许这段代码毫无意义)

2 个答案:

答案 0 :(得分:2)

您可以使用<algorithm>标题中的std::move算法。

auto it = std::move(data, data + T, var);

检查T是否不大于100.但移动char并没有比复制更多的好处。

答案 1 :(得分:2)

该行

Foo f( std::move(v) );

对GCC,Clang和Intel来说是合法的。然而,Visual Studio会抱怨并产生

error C2664: 'Foo::Foo(const Foo &)' : cannot convert parameter 2 from 'char [100]' to 'char (&&)[100]'
1>          You cannot bind an lvalue to an rvalue reference

这对我来说似乎是个错误。实际上,v是左值,但std::move将其转换为右值参考。

由于字符数组不可移动,虽然合法,但我认为通过右值引用获取它们并没有多大用处。如果您确实希望编译代码,则解决方法是使f采用常规(左值)引用并删除调用站点上的std::move。或者甚至更好,让f指向char*f不需要是模板)。在这种情况下,调用f(v)会将v[0]的地址(即v的第一个元素)传递给f。这是所谓的数组到指针转换,由编译器隐式执行。

然而,正如其他人指出的那样,行

    data = std::move(var);
    var = 0;

对所有编译器都是非法的。 datavar是数组(或对数组的引用),并且数组不可分配。例如,每个编译器var = 0;引发的错误如下:

GCC

error: incompatible types in assignment of 'int' to 'char [100]'

锵:

error: array type 'char [100]' is not assignable

英特尔:

error: expression must be a modifiable lvalue

Visual Studio:

error C2440: '=' : cannot convert from 'int' to 'char [100]'