Std::make_shared, Std::unique_ptr和move构造函数

std::make_shared, std::unique_ptr and move constructors

本文关键字:Std 构造函数 move ptr make shared unique      更新时间:2023-10-16

使用clang 3.0/libc++编译以下代码:

#include <memory>
class Foo
{
public:
    Foo()
        : mem_(new int(10))
    {
    }
    std::unique_ptr<int> mem_;
};
int main()
{
    auto foo = std::make_shared<Foo>();
    return 0;
}

但是这个没有(添加了std::string参数):

#include <memory>
#include <string>
class Foo
{
public:
    Foo(const std::string& s)
        : mem_(new int(10))
    {
    }
    std::unique_ptr<int> mem_;
};
int main()
{
    auto foo = std::make_shared<Foo>("aaa");
    return 0;
}

Clang抱怨使用了已删除的构造函数。对我来说,这没有意义,因为std::make_shared不应该复制Foo实例,这是唯一会触发对std::unique_ptr的(已删除的)复制构造函数的调用的事情。

但是你瞧,只要我显式地定义了一个move构造函数,它就会编译。

#include <memory>
#include <string>
class Foo
{
public:
    Foo(const std::string& s)
        : mem_(new int(10))
    {
    }
    Foo(Foo&& other)
        : mem_(std::move(other.mem_))
    {
    }
    std::unique_ptr<int> mem_;
};
int main()
{
    auto foo = std::make_shared<Foo>("aaa");
    return 0;
}

现在,问题:

  1. 为什么它在第一个例子中编译而不是第二个例子?
  2. std::make_shared在构建对象时可以复制/移动对象吗?
  3. 为什么添加一个移动构造器修复这个问题?我不记得添加非默认构造函数应该抑制隐式move构造函数。

编辑:检查和所有的例子似乎与gcc 4.5.1编译良好(通过ideone.com),我怀疑这是clang/libc++错误的情况下,但问题2和3仍然存在,加上我想知道哪个编译器更"正确"。

为什么在第一个例子中可以编译,而在第二个例子中不能?

这是一个libc++错误。我正在努力解决这个问题…

std::make_shared可以在构造对象时复制/移动对象吗?

不,我不相信它可以。

为什么添加move构造函数可以解决这个问题?我不记得了添加非默认构造函数应该抑制隐式移动构造函数。

在你使用的clang版本中,隐式move构造函数还没有实现。

固定:http://llvm.org/bugs/show_bug.cgi?id=11616