设置 class 成员 unique_ptr<T[]> 数组而不复制

Set class member unique_ptr<T[]> array without copying

我有一个 class,其中包含一个由 unique_ptr 管理的 C 风格数组。我想提供一个构造函数:

class A {
  unique_ptr<T[]> p;
public:
  A(int d, X x) : p(new T[d]) {
    //Transfer from x to p without copying
  }
}

这样我就可以用类似的东西构建我的对象:

int main(..) {
  A a{n,{expr1,expr2,..}};
}

其中 {expr1,expr2,..} 包含初始化的值(在运行时计算)。由于这个列表是临时的,在我看来构建它是浪费资源,将它的值复制到实际对象中并丢弃它。

我相信有了移动语义、右值和 C++11 的所有优秀特性,应该有一个解决这个简单任务的方法,但我找不到它(我是 C++ 的新手)。

我想坚持使用 C 风格的数组,不要转向 std::vectors。有解决办法吗?

我想在这里提出两点。

  1. AFAICS,与使用 std::vector<T> 的标准 C++ 解决方案相比,std::unique_ptr<T[]> 为您提供的好处微乎其微,即减少内存占用(容器占用 64 字节而不是 128 字节本身在 64 位机器上,也可能使用堆的数量),但请参阅讨论 here。任何 C++ 新手都应该坚持 std::vector.

  2. 移动语义仅对在堆上管理内存的对象有益 ('free store')。因此,只有当您的 expr1expr2 等对象本身跟踪分配的内存时,移动才有意义。这里没有出现这种情况,所以直接复制。

可以,可以使用完美转发:

#include <memory>
#include <string>

struct S
{
    S(int) {}
    S(S const&) = delete;
    S(S&&) = default;
};

template<typename T>
struct A
{
    std::unique_ptr<T[]> p;

    template<typename... Args>
    A(int d, Args&&... args)
        : p(new T[sizeof...(args)]{std::forward<Args>(args)...})
    {
    }
};

int main()
{
    A<int> a(0, 1, 2, 3, 4);

    A<std::string> b(0, "hello", "world!", "\n");

    S s(0);
    A<S> c(0, std::move(s), 2, 3);
}