Q:

Correct way to write move constructor with unique_ptr member (crash)

The following code will crash under Visual Studio 2013
I'm wondering why : what's the correct way to write a move constructor in such a case ?
Removing the move constructor solves the problem.
Is it a bug of VC++ or is this code wrong ?
What would be different in the default definition of the move constructor that makes this code not crash whereas my own definition does ?
#include <memory>
#include <vector>

class A
{};

class Foo
{
public:
    Foo(std::unique_ptr<A> ref) : mRef(std::move(ref)) {}
    Foo(Foo&& other) : mRef(std::move(other.mRef)) {}

    Foo(const Foo& other) {}
    Foo& operator=(const Foo& other) { return *this; }

protected:
    std::unique_ptr<A> mRef;
};

int main(int argc, char *argv[])
{
    std::vector<Foo>({ Foo(std::make_unique<A>()), Foo(std::make_unique<A>()) });
    // Crash : Debug Assertion Failed !
    // Expression : _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
}

It might be somehow related to this, right ?
Double delete in initializer_list vs 2013
Here is the actual code with fleshed out copy constructor and assignment, but the bug is exactly the same
class A
{
public:
     std::unique_ptr<A> clone() { return std::make_unique<A>(*this); }
};

class Foo
{
public:
    Foo(std::unique_ptr<A> ref) : mRef(std::move(ref)) {}
    Foo(Foo&& other) : mRef(std::move(other.mRef)) {}

    Foo(const Foo& other) : mRef(other.mRef->clone()) {}
    Foo& operator=(const Foo& other) { mRef = other.mRef->clone(); return *this; }

protected:
    std::unique_ptr<A> mRef;
};

A:

This sounds like a VS-2013 bug.  But it also looks like your code, though well-formed, is probably not doing what you want it too (however only you can say that for sure).
I added a print statement to your Foo:
class Foo
{
public:
    Foo(std::unique_ptr<A> ref) : mRef(std::move(ref)) {}
    Foo(Foo&& other) : mRef(std::move(other.mRef)) {}

    Foo(const Foo& other) {}
    Foo& operator=(const Foo& other) { return *this; }

    friend std::ostream&
    operator<<(std::ostream& os, const Foo& f)
    {
        if (f.mRef)
            os << *f.mRef;
        else
            os << "nullptr";
        return os;
    }

protected:
    std::unique_ptr<A> mRef;
};

And I added a print statement to your main as well:

aside:  I also added identity/state to your A so that it was easier to see what is going on.

int main(int argc, char *argv[])
{
    std::vector<Foo> v({ Foo(std::make_unique<A>(1)), Foo(std::make_unique<A>(2)) });
    // Crash : Debug Assertion Failed !
    // Expression : _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
    for (const auto& p : v)
        std::cout << p << '\n';
}

For me this outputs:
nullptr
nullptr

which I believe is the correct output.
One can not move from an initializer_list, and thus the vector constructor invokes Foo's copy constructor which just default constructs unique_ptr.
Indeed if one removes the Foo copy constructor, which should be implicitly deleted then (or you could explicitly delete it), the program should not compile.
To really make this work, you have to give Foo an operational copy constructor.  Perhaps something like this:
    Foo(const Foo& other)
        : mRef(other.mRef ? new A(*other.mRef) : nullptr)
    {}

So in summary, I think both the compiler and the current code get awards for bugs.  Though from the comments, it sounds like the current code bug is simply an artifact of correctly reducing the code to isolate the problem.
VS-2013 bug.
As for your move constructor, it is fine.  Though it would be even better if implemented with = default.  If you do so, it will automatically inherit a noexcept spec.  Such a spec should not be taken lightly.  It is most important for efficient use of vector<Foo>. 
My understanding is that VS-2013 does not understand either defaulted move members nor noexcept.
My anecdotal experience with VS-2013 is that the number of compiler bugs one experiences is directly proportional to the use of curly braces.  I am hopeful that VS-2015 will contradict this experience.  In the meantime I recommend avoiding using construction expressions that involve {}.

Update
Your updated copy members in:
class Foo
{
public:
    Foo(std::unique_ptr<A> ref) : mRef(std::move(ref)) {}
    Foo(Foo&& other) : mRef(std::move(other.mRef)) {}

    Foo(const Foo& other) : mRef(other.mRef->clone()) {}
    Foo& operator=(const Foo& other) { mRef = other.mRef->clone(); return *this; }

protected:
    std::unique_ptr<A> mRef;
};

have potential nullptr-dereference bugs.  If other is in a moved-from state, the ->clone() is going to dereference a nullptr.  Technically you can get away with this if you are very, very careful.  However it will be very easy for you to accidentally hit this bug.

