STL向量上的怪异复制构造函数错误

时间:2018-07-23 22:26:22

标签: c++ c++11 game-engine copy-constructor

因此,我目前正在完成我的物理引擎,无法确定类的问题以及为什么编译器报告在使用向量时删除其副本构造函数的问题。


这是我的课程

const real baumgarteCoef = 0.5f;
// based on GoblinPhysics'
// https://github.com/chandlerprall/GoblinPhysics/blob/master/src/classes/Constraints/ContactConstraint.js
class ContactConstraint : public Constraint {
public:
    ContactConstraint(PhysicalObject* objA, PhysicalObject* objB, const Vector3& position,
                       const Vector3& normal, real penetration)
        : Constraint(objA, objB, (u32)1) {
        collisionPosition = position;
        collisionNormal = normal;
        this->penetration = penetration;
        real r1 = objA->getRestitution();
        real r2 = objB->getRestitution();
        restitutionCoef = Math::SquareRoot(r1 * r2);
        rows[0].lowerLimit = 0.f;
        rows[0].upperLimit = Math::PositiveInfinity;
        collisionPosA = objA->getInverseRotation().rotate(position - objA->getPosition() +
                                                          normal * penetration);
        collisionPosB = objB->getInverseRotation().rotate(position - objB->getPosition() -
                                                          normal * penetration);
    }

    ContactConstraint(const ContactConstraint& c) = default;

    void update(real timeElapsed) {
        auto& row = rows[0];

        if (objA->isStatic()) {
            row.jacobian[0] = 0.f;
            row.jacobian[1] = 0.f;
            row.jacobian[2] = 0.f;
            row.jacobian[3] = 0.f;
            row.jacobian[4] = 0.f;
            row.jacobian[5] = 0.f;
        } else {
            row.jacobian[0] = -collisionNormal.x();
            row.jacobian[1] = -collisionNormal.y();
            row.jacobian[2] = -collisionNormal.z();

            Vector3 v = collisionPosition - objA->getPosition();
            Vector3 v2 = v.cross(collisionNormal);
            row.jacobian[3] = -v2.x();
            row.jacobian[4] = -v2.y();
            row.jacobian[5] = -v2.z();
        }

        if (objB->isStatic()) {
            row.jacobian[6] = 0.f;
            row.jacobian[7] = 0.f;
            row.jacobian[8] = 0.f;
            row.jacobian[9] = 0.f;
            row.jacobian[10] = 0.f;
            row.jacobian[11] = 0.f;
        } else {
            row.jacobian[6] = collisionNormal.x();
            row.jacobian[7] = collisionNormal.y();
            row.jacobian[8] = collisionNormal.z();

            Vector3 v = collisionPosition - objB->getPosition();
            Vector3 v2 = v.cross(collisionNormal);
            row.jacobian[9] = v2.x();
            row.jacobian[10] = v2.y();
            row.jacobian[11] = v2.z();
        }

        // Apply penetration error.
        row.bias = baumgarteCoef * penetration / timeElapsed;
        // Apply restitution
        Vector3 velocity = objA->getLinearVelocity() +
                        collisionPosA.cross(objA->getAngularVelocity()) -
                        objB->getLinearVelocity() - collisionPosB.cross(objB->getAngularVelocity());
        real restitution = (collisionNormal.dot(velocity)) * restitutionCoef;
        row.bias += restitution;
    }

private:
    Vector3 collisionPosition;
    Vector3 collisionNormal;
    Vector3 collisionPosA;
    Vector3 collisionPosB;
    real penetration;
    real restitutionCoef;
};

及其父类

// based on GoblinPhysics'
// https://github.com/chandlerprall/GoblinPhysics/blob/master/src/classes/Constraints/ConstraintRow.js
class Constraint {
public:
    class Row {
    public:
        Constraint* parent;
        real jacobian[12];
        real derivedMass[12];
        real effectiveMass;
        real lowerLimit;
        real upperLimit;
        real bias;
        real multiplier;
        real multiplierCache;
        real eta;

        void computeDerivedMass();
        void computeEffectiveMass();
        void computeEta(real timeDelta);
    };

    Constraint(PhysicalObject* objectA, PhysicalObject* objectB, u32 numRows) {
        objA = objectA;
        objB = objectB;
        rows = std::make_unique<Row[]>(numRows);
        this->numRows = numRows;
        for (u32 i = 0; i < numRows; i++)
            rows[i].parent = this;
        breakingThreshold = 0.f;
        active = true;
    }

    Constraint(const Constraint& c) = default;
    PhysicalObject* objA;
    PhysicalObject* objB;
    std::unique_ptr<Row[]> rows;
    Vector3 lastImpulse;
    u32 numRows;
    real breakingThreshold;
    bool active;

    virtual void update(real timeElapsed) = 0;
};

错误(上帝怜悯,因为编译器可能会压缩它)

[  9%] Building CXX object src/CMakeFiles/kepler3d.dir/PhysicsEngine/PhysicsEngine.cpp.obj
In file included from D:/msys64/mingw64/include/c++/7.3.0/memory:64:0,
                 from D:/msys64/home/ferna/Kepler3D/src/Architecture/Command.h: ,
                 from D:/msys64/home/ferna/Kepler3D/src/Architecture/Architecture.h:3,
                 from D:/msys64/home/ferna/Kepler3D/src/PhysicsEngine/PhysicsEngine.cpp:2:
D:/msys64/mingw64/include/c++/7.3.0/bits/stl_construct.h: In instantiation of 'void std::_Construct(_T1*, _Args&& ...) [with _T1 = Kepler3D::ContactConstraint; _Args = {Kepler3D::ContactConstraint}]':
D:/msys64/mingw64/include/c++/7.3.0/bits/stl_uninitialized.h:83:18:   required from 'static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<Kepler3D::ContactConstraint*>; _ForwardIterator = Kepler3D::ContactConstraint*; bool _TrivialValueTypes = false]'
D:/msys64/mingw64/include/c++/7.3.0/bits/stl_uninitialized.h:134:15:   required from '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<Kepler3D::ContactConstraint*>; _ForwardIterator = Kepler3D::ContactConstraint*]'
D:/msys64/mingw64/include/c++/7.3.0/bits/stl_uninitialized.h:289:37:   required from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<Kepler3D::ContactConstraint*>; _ForwardIterator = Kepler3D::ContactConstraint*; _Tp = Kepler3D::ContactConstraint]'
D:/msys64/mingw64/include/c++/7.3.0/bits/stl_uninitialized.h:311:2:   required from '_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = Kepler3D::ContactConstraint*; _ForwardIterator = Kepler3D::ContactConstraint*; _Allocator = std::allocator<Kepler3D::ContactConstraint>]'
D:/msys64/mingw64/include/c++/7.3.0/bits/vector.tcc:426:6:   required from 'void std::vector<_Tp, _Alloc>::_M_realloc_insert(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {Kepler3D::PhysicalObject*&, Kepler3D::PhysicalObject*&, const Kepler3D::Vector3&, const Kepler3D::Vector3&, float&}; _Tp = Kepler3D::ContactConstraint; _Alloc = std::allocator<Kepler3D::ContactConstraint>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<Kepler3D::ContactConstraint*, std::vector<Kepler3D::ContactConstraint> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = Kepler3D::ContactConstraint*]'
D:/msys64/mingw64/include/c++/7.3.0/bits/vector.tcc:105:21:   required from 'std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {Kepler3D::PhysicalObject*&, Kepler3D::PhysicalObject*&, const Kepler3D::Vector3&, const Kepler3D::Vector3&, float&}; _Tp = Kepler3D::ContactConstraint; _Alloc = std::allocator<Kepler3D::ContactConstraint>; std::vector<_Tp, _Alloc>::reference = Kepler3D::ContactConstraint&]'
D:/msys64/home/ferna/Kepler3D/src/PhysicsEngine/Dynamics/ConstraintsManager.h:23:82:   required from here
D:/msys64/mingw64/include/c++/7.3.0/bits/stl_construct.h:75:7: error: use of deleted function 'Kepler3D::ContactConstraint::ContactConstraint(const Kepler3D::ContactConstraint&)'
     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }

我不确定父类上的唯一指针是否使派生构造函数成为不可能。我还想补充一点,在任何情况下我都不能直接复制该类(仅Emplace),但是,由于其内部机制,默认情况下,矢量类的复制是


此行导致ConstraintsManager

中的错误
contactConstraints.emplace_back(objA, objB, position, normal, penetration);

2 个答案:

答案 0 :(得分:3)

包含unique_ptr的对象无法复制,因为默认情况下该成员(即rows)不可复制。如果需要复制,则必须提供自己的实现。

据我所知,通过查看错误跟踪,我认为您应该能够移动对象。您是否尝试提供默认的move构造函数?

Constraint(Constraint&& c) = default;

我认为也应该是noexcept

我不确定您是否可以复制和/或移动您的派生类,因为我没有Vector3的定义。

很明显,从错误跟踪中,您需要能够复制(或移动)项目,因为添加矢量时可能需要调整矢量的大小。

尽管,我相信在此示例中,您需要深层复制,在某些情况下,您可能能够存储shared_ptr而不是unique_ptr,然后将自动生成一个浅表复制构造函数。

事实上,它在这里也可能适用,但是您需要注意不要进行意外复制,然后再修改对象,而无需意识到这些数据之间是部分共享的。

答案 1 :(得分:0)

发现了问题。事实证明,由于父类具有unique_ptr而不能派生出复制构造函数,一个简单的解决方案不是为我的数组生成unique_ptr,为此我使用了std :: vector。

为将来参考,unique_ptrs没有复制构造函数,必须按大小写进行处理。