繁体   English   中英

默认构造函数阻止调用emplace_back

[英]Default constructor prevents from calling emplace_back

似乎添加默认构造函数会阻止调用emplace_back并产生错误消息:“静态断言失败:类型不可分配”(gcc 5.3 with -std = c ++ 14)。 这是一个简单的代码,说明了这个问题:

class A {
public:
    int a;
    A() = default;
    A(int a) {
        this->a = a;
    }
    A(A const & a) = delete;
    A& operator =(A const & a) = delete;
    A(A && a) = default;
    A& operator =(A && a) = default;
};

int main() {

    A a(4);
    std::vector<A> vec;
    vec.emplace_back(std::move(a)); // Error: type is not assignable
    return 0;
}

删除默认构造函数时,错误消失了! 此外,如果定义了默认构造函数(即使它什么都不做),错误也会消失:

class A {
public:
    int a;
    A() {
    }
    A(int a) {
        this->a = a;
    }
    A(A const & a) = delete;
    A& operator =(A const & a) = delete;
    A(A && a) = default;
    A& operator =(A && a) = default;
};

int main() {

    A b;
    A a(4);
    std::vector<A> vec;
    vec.emplace_back(std::move(a)); // Error gone
    return 0;
}

似乎“A()=默认;” 是导致问题的原因。 这是编译器的一部分正常行为还是一个错误?

这是一个libstdc ++ bug(编辑:报告为bug 69478 )。

简而言之,libstdc ++的std::vector ,与此相关,使用std::uninitialized_copy (与移动迭代器配对)在重新分配时移动元素,如果类型很简单且迭代器的引用类型是可分配的,则减少为std::copy (即,概念上使用的赋值运算符是可用的)。

然后, std::copy用于指向普通类型的指针(或者在我们的例子中,包含指针的move_iterator )又被优化为对memmove的调用以及对is_copy_assignable的检查。 当然,在这种情况下检查是错误的,因为uninitialized_copy与移动迭代器配对,只需要移动可构造的东西。

如果您没有默认构造函数或者默认构造函数是用户定义的,那么该类并不简单,因此您不会遇到触发此错误的代码路径。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM