不可复制类的问题

时间:2011-01-04 21:50:50

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

我有一些不可复制的课程。我没有调用任何复制操作符或构造函数,并且此代码编译良好。但后来我升级到Visual Studio 2010 Ultimate而不是Professional。现在编译器正在调用复制构造函数 - 即使应该调用移动构造函数。例如,在以下代码段中:

inline D3D9Mesh CreateSphere(D3D9Render& render, float radius, float slices) {
    D3D9Mesh retval(render);
    /* ... */
    return std::move(retval);
}

错误:无法创建复制构造函数,因为该类是不可复制的。但是,我非常明确地提出了它。

编辑:

class D3D9Mesh 
: public Monitor<D3D9Mesh> 
{
public:
    std::unique_ptr<ID3DXMesh, COMDeleter> Mesh;
    std::unique_ptr<ID3DXBuffer, COMDeleter> Adjacency;

    inline D3D9Mesh(D3D9Render& ref)
    : Monitor<D3D9Mesh>(&ref) 
    {
    }
};

其中Monitor是一个可复制/等的简单类。这是unique_ptrs,显然不是编译器的犹太人。

监视器的代码:

class D3DCommon {};
template<typename T> class Monitor : public D3DCommon {
protected:
    D3D9Render* render;
    Monitor(D3D9Render* ptr) 
    : render(ptr) {
        render->AddPointer(static_cast<T*>(this));
    }
    Monitor(Monitor&& ref) {
        render->AddPointer(static_cast<T*>(this));
    }
    Monitor(const Monitor& ref) {           
        render->AddPointer(static_cast<T*>(this));
    }
    ~Monitor() {
        render->RemovePointer(static_cast<T*>(this));
    }
public:
    D3D9Render& GetRender() {
        return *render;
    }
};

2 个答案:

答案 0 :(得分:1)

这很奇怪。你的D3D9Mesh课程是如何实施的? 以下代码为vs2010终极版编译好了:

#include <iostream>
struct S
{
   S(){std::cout << "ctor\n";}
   S(S&&){std::cout << "move ctor\n";}
   S& operator=(S&&){std::cout << "move op=\n";return *this;}

private:
   S(const S&);
   S& operator=(const S&);


};

inline S CreateSphere() 
{
    S s;
    return s;
}


int main()
{
   S s = CreateSphere(); // NRVO
   s = CreateSphere(); // move
}

PS:如果“something”是在函数中创建的局部变量,则不要写return std :: move(something)。编译器已经知道从函数返回一个局部变量是一个临时值(一个右值)。使用std :: move重新进行自我调整不会让它更好地移动,但它会阻止vs2010进行一些优化,例如NRVO。

答案 1 :(得分:1)

MSVC不执行隐式移动构造函数。你需要自己做:

class D3D9Mesh 
: public Monitor<D3D9Mesh> 
{
public:   
    inline D3D9Mesh(D3D9Render& ref)
    : Monitor(&ref) // don't need to re-state template argument, by the way
    {
    }

    D3D9Mesh(D3D9Mesh&& other)
    : Monitor(std::move(other))
    {}
};

现在它可以移动了。