数组在C++中作为参数传递时隐式转换为容器类

Array converted implicitly to container class when passed as argument in C++

本文关键字:转换 容器类 参数传递 C++ 数组      更新时间:2023-10-16

我正在做一个项目,在处理代码时,我遇到了以下特殊情况。

我有两节课。第一个在表示笛卡尔坐标的数组中保持三个浮点,并定义了获取这些点的方法;

class foo
{
protected:
    float m_Coordinates[3];
public:
    foo(float coordinates[3]);
    void GetPoints(int resultArray[]);
};
foo::foo(int coordinates[3])
{
    std::copy(coordinates, coordinates+3, m_Coordinates);
}
void foo::GetPoints(float resultArray[])
{
    std::copy(m_Coordinates, m_Coordinates+3, resultArray);
}

第二个类也存储一个浮点数组,但它的构造函数使用foo作为包装类来传递值:

class bar
{
protected:
    float m_MoreCoordinates[3];
public:
    bar(foo f);
};
bar::bar(foo f)
{
    f.GetPoints(m_MoreCoordinates);
    //m_MoreCoordinates is passed by reference, so the values in
    //m_MoreCoordinates are equal to the values in f.m_Coordinates
    //after this line executes
}

请忽略这样一个事实:我对这段代码采取的方法简直太可怕了。它最初是一个使用数组的实验。将它们作为参数传递,将它们作为返回类型等

好的。在这里我发现了一些奇怪的东西。如果我声明一个浮点数组,并将它们作为参数传递给bar的构造函数,编译器将生成一个类foo的实例,并将其传递给bar。参见下面的示例代码:

int main(int argv, char** argc)
{
    float coordinates[] = {1.0f, 2.1f, 3.0f};

    //Here the compiler creates an instance of class foo and passes 
    //coordinates as the argument to the constructor. It then passes 
    //the resulting class to bar's constructor.
    bar* b = new bar(coordinates);
    //Effectively, the compiler turns the previous line into
    //bar* b = new bar(foo(coordinates));
    return 0;
}

当我看到这一点时,我认为这是代码中一个非常整洁的功能,并想知道它是如何发生的以及为什么发生的。这样做安全吗?我不明白它是如何工作的,所以我不想依赖它。如果有人能解释它是如何运作的,我真的很感激。

编辑:感谢Mankarse指出了转换将如何进行。最初,我有:

//Effectively, the compiler turns the previous line into
//bar* b = new bar(*(new foo(coordinates)));

正如您所猜测的,编译器正在隐式创建一个foo对象并将其传递给bar。通常,这被认为有点危险,因为foo是在不知情的情况下构造的,为了避免这种情况,可以将foo的构造函数声明为explicit。在这种情况下,编译器不会从浮点数组中隐式创建foo,您将得到一个编译器错误。

当你考虑它时,你会一直使用它。考虑以下内容:

void foo(std::string argument);

然后,假设您使用字符串文字调用此函数:

foo("argument");

这与相同

std::string argument("argument");
foo(argument);

这是一个非常有用的功能。