在推荐链接的最后一个答案中(如何使new[]
默认初始化原始类型数组?), 我想出了以下小例子:
#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
在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;
}
输出:与上面的相同
在coliru上的实时演示
std::vector
。 - Daniel Langr