按照推荐链接中的最后一个答案
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 也可以编译的移动构造函数:
#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