不能初始化参数

时间:2018-10-29 14:14:26

标签: c++ compilation

是否可以向必须尚未初始化的函数参数添加编译器级别的约束,例如可以的:

void f(SomeClass& a) { /* ... */ }

int main() {
    f(new SomeClass());
    return 0;
}

虽然以下内容不可行:(由于a已初始化并存储在变量中)

int main() {
    SomeClass a;
    f(a);
    return 0;
}

3 个答案:

答案 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);