如何初始化由unique_ptr管理的数组的元素?

时间:2018-09-07 06:50:28

标签: c++ c++11 std unique-ptr

我们知道资源获取是初始化(RAII),我寻找了一种语法来初始化由unique_ptr管理的,具有参数(没有默认参数)的对象数组,但是没有找到任何示例, Cppreference中有一个构造int

int size = 10; 
std::unique_ptr<int[]> fact(new int[size]);

我怎么这样写:

class Widget
{
 Widget(int x, in y):x_(x),y_(y)
 {}
 int x_,y_;
};

 std::unique_ptr<Widget[]> fact(new Widget[size]);

2 个答案:

答案 0 :(得分:3)

按照推荐链接中的最后一个答案
How can I make new[] default-initialize the array of primitive types?
我想到了以下小例子:

#include <iostream>
#include <memory>
#include <string>

class Widget {
  private:
    std::string _name;
  public:
    Widget(const char *name): _name(name) { }
    Widget(const Widget&) = delete;
    const std::string& name() const { return _name; }
};

int main()
{
  const int n = 3;
  std::unique_ptr<Widget[]> ptrLabels(
    new Widget[n]{
      Widget("label 1"),
      Widget("label 2"),
      Widget("label 3")
    });
  for (int i = 0; i < n; ++i) {
    std::cout << ptrLabels[i].name() << '\n';
  }
  return 0;
}

输出:

label 1
label 2
label 3

Live Demo on coliru

诀窍是使用初始化列表。

我有点不确定这是否涉及复制构造(在小部件类库中经常禁止使用复制构造)。可以肯定的是,我写了Widget(const Widget&) = delete;

我不得不承认这适用于C ++ 17,但不适用于此。


我在第一个例子中摆弄了一些。

我也尝试过

new Widget[n]{
  { "label 1" },
  { "label 2" },
  { "label 3" }
});

取得成功,直到我意识到我忘了在第一个示例中创建构造函数explicit。 (通常,小部件集不允许这样做-以防止意外转换。)修复此问题后,它不再编译。

介绍了即使在C ++ 11中也可以编译的move构造函数:

#include <iostream>
#include <memory>
#include <string>

class Widget {
  private:
    std::string _name;
  public:
    explicit Widget(const char *name): _name(name) { }
    Widget(const Widget&) = delete;
    Widget(const Widget &&widget): _name(std::move(widget._name)) { }
    const std::string& name() const { return _name; }
};

int main()
{
  const int n = 3;
  std::unique_ptr<Widget[]> ptrLabels(
    new Widget[n]{
      Widget("label 1"),
      Widget("label 2"),
      Widget("label 3")
    });
  for (int i = 0; i < n; ++i) {
    std::cout << ptrLabels[i].name() << '\n';
  }
  return 0;
}

输出:如上

Live Demo on coliru

答案 1 :(得分:1)

您可以使用展示位置新删除器和自定义删除器:

public class tester{
    public static void main(String[] args){
        Human bob = new Human();
        System.out.println(bob.toString());
    }
}

如预期的那样,我们有两行输出:

  

0123456789
  0123456789

请注意,由于这里的删除器是有状态的,因此无法使用class Widget { public: int i; Widget(int i) : i(i) {} ~Widget() { std::cout << i; } }; class WidgetDeleter { int _size; public: WidgetDeleter(int size) : _size(size) {} void operator()(Widget* w) { for (int i = 0; i < _size; ++i) w[i].~Widget(); } }; void main() { const int widgetsCount = 10; auto widgets = std::unique_ptr<Widget[], WidgetDeleter>( (Widget*)(new byte[widgetsCount * sizeof(Widget)]), WidgetDeleter(widgetsCount)); for (int i = 0; i < widgetsCount; ++i) new (widgets.get() + i)Widget(i); for (int i = 0; i < widgetsCount; ++i) std::cout << widgets[i].i; std::cout << std::endl; } [unique.ptr.single.ctor#8]

的默认构造函数