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

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

本文关键字:文字 常量 引用 C++      更新时间:2023-10-16

如果我用一个整数作为参数(而不是"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)"调用使用泛型构造函数(int_a)创建一个新对象。这种建筑有名字吗?程序员不应该在传递参数之前显式地构造一个对象吗?像这样:

func(generic(8));

单独传递整数(除了节省时间之外)有什么好处吗?

此行为是重载解决过程的一部分,具体而言。

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

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

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

  • 完全匹配
  • 促销
  • 转换

这意味着签名的精确匹配胜过需要升级的匹配,需要升级的比赛胜过需要转换的比赛。

有关如何应用隐式转换的信息,请参阅上面链接的文档的"隐式转换序列排名"。

这种建筑有名字吗?程序员不应该在传递参数之前显式地构造一个对象吗?

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

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

来自cppreference页面的摘录:

在没有函数说明符explicit的情况下声明的构造函数称为转换构造函数。

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

单独传递整数(除了节省时间之外)有什么好处吗?

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