传递给 const 引用的 C++ 文字会导致自动构造

C++ literal passed to const reference leads to automatic construction

如果我使用一个整数作为参数(而不是 'generic' 对象)调用 "func(const generic& ref)",将调用构造函数 generic(int _a) 来创建一个新对象。

class generic {
public:
    int a;
    generic() {}
    generic(int _a) : a(_a) {
        std::cout << "int constructor was called!";
    }
    generic(const generic& in) : a(in.a) {
        std::cout << "copy constructor was called!";
    }
};

void func(const generic& ref) {
    std::cout << ref.a;
}

int main() {
    generic g(2);
    func(g); // this is good.
    func(generic(4)); // this is good.
    func(8); // this is good...... ?
    return 0;
}

最后的 "func(8)" 调用使用构造函数 generic(int _a) 创建了一个新对象。这种建筑有名字吗?程序员不应该在传递参数之前显式构造一个对象吗?像这样:

func(generic(8));

单独传递整数是否有任何好处(除了节省时间)?

Is there a name for this kind of construction? Shouldn't the programmer explicitly construct an object before passing the argument?

如果您不希望这种情况发生,您可以将 explicit specifier 添加到您的构造函数中:

explicit generic(int _a) : a(_a)
{
    std::cout << "int constructor was called!";
}

cppreference 页面的摘录:

A constructor that is declared without the function specifier explicit is called a converting constructor.

默认情况下,在这种情况下允许隐式构造函数调用。

Is there any benefit in passing the integer alone (other than saving time)?

无论您使用 func(8) 还是 func(generic(8)) 调用该方法都不会改变执行的代码 给定您编写的代码。如果您要添加一个 func 的重载,它采用 int 而不是 generic,那么调用会突然变得不同。因此,尽管这最终是一个见仁见智的问题,但我认为您最好使用 func(generic(8)).

来明确说明

此行为是 overload resolution 过程的一部分 - 特别是。

当您调用 func() 时,编译器会构建一个候选列表。只有一个候选项,func(const generic& ref),因此编译器试图弄清楚如何进行调用。

它看到没有定义func(int),所以它试图找到从intgeneric的转换路径。由于 generic 的构造函数采用 int,并且没有其他转换允许执行相同的调用,因此编译器采用构造+调用路径。

编译器按照优先级从高到低的顺序检查三件事:

  • 完全匹配
  • 晋升
  • 转化

这意味着签名的完全匹配胜过需要升级的匹配,而需要升级的匹配胜过需要转换的匹配。

有关如何应用隐式转换的信息,请参阅上面链接的文档的 "Ranking of implicit conversion sequences"。