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

C++ 在C+;中作为参数传递时,数组隐式转换为容器类+;,c++,arrays,constructor,instantiation,implicit,C++,Arrays,Constructor,Instantiation,Implicit,我在做一个项目,在玩代码的时候,我遇到了以下奇怪的事情 我有两节课。第一种方法在表示笛卡尔坐标的数组中保存三个浮点,并定义获取这些点的方法 class foo { protected: float m_Coordinates[3]; public: foo(float coordinates[3]); void GetPoints(int resultArray[]); }; foo::foo(int coordinates[3]) { std::copy(c

我在做一个项目,在玩代码的时候,我遇到了以下奇怪的事情

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

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
s构造函数声明为
explicit
。在这种情况下,编译器不会隐式地从浮点数组创建
foo
,您将得到一个编译器错误。

当您考虑它时,您一直在使用它。考虑以下事项:

void foo(std::string argument);
然后,假设您使用字符串文字调用此函数:

foo("argument");
这与:

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

这是一个非常有用的特性。

编译器实际上将行转换为
bar*b=newbar(foo(坐标))@Mankarse是对的,bar*b=新的bar(*(新的foo(坐标));将泄漏,因为构造函数通过值传递。你永远不会有机会清理它。@Mankarse啊,谢谢你指出这一点。Java简直毁了我。我从来没有注意到那里会有内存泄漏。非常感谢。编译器的行为很有趣。我以前从未见过它这么做。感谢您的解释。人们一直认为具有非托管内存的语言是不安全的。这并不意味着它们不应该被用作一种无价的语言,只是在使用它们之前你应该知道你在做什么。所以我们可以一直依靠编译器来为我们执行这种转换?你说得对,这是一个非常有用的功能。尽管纳文建议谨慎使用,但这似乎是个好建议。即使从可读性的角度来看,依靠编译器从浮点数组创建类的编码也不是很清楚。尽管如此,它还是一个非常有趣的特性。@GaryMunnelly我认为它非常清晰易读,可以在函数定义中传递类型的构造参数。事实上,我认为它通常会使代码在正确使用时更具可读性。不管怎样,每个人都有自己的。