c++ - 你应该如何初始化一个我不知道其内容的 Array 属性?
问题描述
我的代码中指定了以下类。
class Foo{
private:
int myInt;
Bar myList[10];
public:
Foo(){
myInt = 0;
}
void addBar(Bar b){
this->myList[myInt] = b;
myInt ++;
}
};
我收到错误
Foo 的构造函数必须显式初始化没有默认构造函数的成员 myList。
问题是直到运行时我才知道该列表将包含什么,因为用户将Bar
对象添加到列表中 - 而我的Bar
对象没有默认值,需要指定它们。
我应该如何在那里初始化该变量?
这是类的定义Bar
class Bar{
private:
std::string name;
int number;
public:
Bar(std::string name, int number){
name = name;
number = number;
};
这就是我正在做的main()
int main(){
Bar b("Red",1);
Foo f();
f.addBar(b)
return 0;
}
解决方案
好吧,我建议只使用 astd::vector<Bar>
而不是尝试使用原始数组。关于数组的事情是你不能离开它的任何对象未构造。如果你真的想知道如何自己实现它,你首先在数组中使用不同的类型,不需要任何初始化,然后根据需要重用该内存来创建和销毁对象。
“不同类型”是std::aligned_storage_t
. 方便的是,页面上的示例正是我们想要的。
// template<class T, std::size_t N>
// class static_vector
// T = Bar; N = 10
class Foo {
// properly aligned uninitialized storage for 10 Bars
std::aligned_storage_t<sizeof(Bar), alignof(Bar)> data[10];
std::size_t size = 0;
public:
// compiler-provided default constructor does not initialize data
Foo() = default;
void addBar(Bar b) {
if(size >= 10) throw std::bad_alloc{}; // possible error handling
// reuse uninitialized memory for a Bar
new(&data[size]) Bar(std::move(b));
size++; // if constructor can throw, this must be after the constructor!
}
Bar const &operator[](std::size_t pos) const noexcept {
return *std::launder(reinterpret_cast<Bar const*>(&data[pos]));
}
Bar &operator[](std::size_t pos) noexcept {
return *std::launder(reinterpret_cast<Bar*>(&data[pos]));
}
void popBar() {
if(size <= 0) return; // or whatever
operator[](--size).~Bar();
}
// Have to remember to clean up!
~Foo() {
while(size) popBar();
}
// all the other special functions need to be custom...
// we even have to handle cleanup!
Foo(Foo const &other) {
try {
for(std::size_t i = 0; i < other.size; i++) addBar(other[i]);
} catch(...) {
while(size) popBar();
throw;
}
}
Foo(Foo &&other) {
try {
for(std::size_t i = 0; i < other.size; i++) addBar(std::move(other[i]));
} catch(...) {
while(size) popBar();
throw;
}
}
Foo &operator=(Foo const &other) {
while(size > other.size) popBar();
std::size_t i = 0;
for(; i < size && i < other.size; i++) operator[](i) = other[i];
for(; i < other.size; i++) addBar(other[i]);
return *this;
}
Foo &operator=(Foo &&other) {
while(size > other.size) popBar();
std::size_t i = 0;
for(; i < size && i < other.size; i++) operator[](i) = std::move(other[i]);
for(; i < other.size; i++) addBar(std::move(other[i]));
return *this;
}
// should also add a way to check size, maybe clear, etc.
};
另外,你Bar
应该这样写:
class Bar {
std::string name;
int number;
public:
Bar(std::string name, int number) : name(std::move(name)), number(number) { }
};
和你的main
int main() {
Foo f; // Foo f(); declares a function!
f.addBar({"Red", 1});
return 0;
}
推荐阅读
- terraform - 在 Terraform 的输出字符串中转义引号
- reactjs - 未捕获的 RangeError:React 挂钩获取中超出了最大调用堆栈大小
- c - 通过 Function 传递的参数导致构建错误
- mysql - 如何在列表中分组并填充零
- java - Java 中 BFS 演练的解决方案路径
- cmake - CMake:使用 Ninja 构建时如何处理 add_custom_command 子构建
- angular - Angular Karma Jasmine 错误 ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后已更改
- java - Hadoop - 启动映射作业时出错,退出代码:1
- android - Android vs iOS (Cordova) 中的藏文字体显示问题
- flutter - 如何在颤振中搜索查询uaing sqfit?