是否可以向必须尚未初始化的函数参数添加编译器级别的约束,例如可以的:
void f(SomeClass& a) { /* ... */ }
int main() {
f(new SomeClass());
return 0;
}
虽然以下内容不可行:(由于a
已初始化并存储在变量中)
int main() {
SomeClass a;
f(a);
return 0;
}
答案 0 :(得分:6)
两行之间的阅读是允许的目标
f(g());
其中SomeClass g()
返回类型为SomeClass
的对象?
并且不允许
SomeClass a;
f(a);
仅此而已,您正在查看右值引用:
void f(SomeClass&& arg); // argument is rvalue reference
void f(const SomeClass& arg); // argument is lvalue reference
f(g()); // calls f(SomeClass&&)
SomeClass a;
f(a); // calls f(SomeClass&)
可以故意打败:
f(std::move(a)); // calls f(SomeClass&&)
答案 1 :(得分:1)
有一个关于*
和&
的注意事项。
它们不一样。
函数new SomeClass()
返回的值SomeClass*
与SomeClass&
不同。
因此,由于没有可用的隐式转换,因此您的代码将无法编译。
为您的代码考虑新的结构,例如:
void f(SomeClass* a) { /* ... */ }
int main() {
SomeClass* a = new SomeClass();
f(a);
return 0;
}
答案 2 :(得分:1)
使用“未初始化的”对象(或更确切地说是内存,因为该对象通过构造函数调用对其进行初始化就可以使用)的唯一方法是编写易于出错的代码,该代码更接近C而不是C ++。这是因为C ++类型系统会尽力使您远离未初始化的对象。
如果您真的想走这条路,则可以malloc
分配一个适当的内存块并将其传递给f
,然后使用placement new
来初始化该对象记忆。从理论上讲,您可以将其包装在另一个具有这些语义的类中。
有些相关,有些标准容器可能会满足您的需求,但是没有一个主要的语义/目的是持有“未初始化的”对象:
std::unique_ptr
:
void f(std::unique_ptr<SomeClass>& a) { assert(!a); /* Initialize a... */ }
std::unique_ptr<SomeClass> a; // a is empty
f(a);
std::optional
:
void f(std::optional<SomeClass>& a) { assert(!a.has_value()); /* Initialize a... */ }
std::optional<SomeClass> a; // a is empty
f(a);