C++ 参数不能初始化
是否可以将编译器级别的约束添加到函数参数中,这些参数必须尚未初始化,例如,可以执行以下操作:C++ 参数不能初始化,c++,compilation,C++,Compilation,是否可以将编译器级别的约束添加到函数参数中,这些参数必须尚未初始化,例如,可以执行以下操作: void f(SomeClass& a) { /* ... */ } int main() { f(new SomeClass()); return 0; } 但以下情况不正常:(因为a已初始化并存储在变量中) 字里行间的阅读,是允许的目标 f(g()); 其中SomeClass g()返回类型为SomeClass的对象 不允许 SomeClass a; f(a); 如果
void f(SomeClass& a) { /* ... */ }
int main() {
f(new SomeClass());
return 0;
}
但以下情况不正常:(因为a
已初始化并存储在变量中)
字里行间的阅读,是允许的目标
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&&)
关于
*
和&
有一个考虑因素。
它们不一样。
函数newsomeclass()
返回一个与SomeClass&
不同的值SomeClass*
。
因此,您的代码将无法编译,因为没有可用的隐式转换
为您的代码考虑一种新的结构,如:
void f(SomeClass* a) { /* ... */ }
int main() {
SomeClass* a = new SomeClass();
f(a);
return 0;
}
唯一的方法是使用“未初始化”对象(或者是内存,因为对象使用构造函数调用来初始化它),它是编写易于接近C的错误倾向代码,而不是C++。这是因为C++类型的系统试图让你远离未初始化的对象。 如果你真的想沿着这条路走下去,你需要
malloc
一个合适的内存块,然后把它传递给f
,然后用它来初始化内存中的对象。理论上,您可以将其封装在另一个具有这些语义的类中
与此相关的是,有些标准容器可能在某种程度上满足您的需求,但没有一个容器具有保存“未初始化”对象的主要语义/目的:
:std::unique\u ptr
void f(std::unique_ptr<SomeClass>& a) { assert(!a); /* Initialize a... */ } std::unique_ptr<SomeClass> a; // a is empty f(a);
new
生成的指针被初始化,而不是一个在堆上分配,另一个在堆栈上。您的两个变量是相同的,都是初始化的。听起来您应该忘记new
,开始查看右值引用和移动语义。new SomeClass()
返回类型为SomeClass*
,而不是SomeClass&
,并且由于两者之间不可能进行转换,因此此类代码无法编译。除此之外,它还以与SomeClass a
相同的方式初始化对象本身。只有存储位置/持续时间不同。您真正想要实现的是什么?为什么传递左值会成为一个问题?
void f(std::unique_ptr<SomeClass>& a) { assert(!a); /* Initialize a... */ }
std::unique_ptr<SomeClass> a; // a is empty
f(a);
void f(std::optional<SomeClass>& a) { assert(!a.has_value()); /* Initialize a... */ }
std::optional<SomeClass> a; // a is empty
f(a);