将实例和大括号括起来的初始化列表传递给函数有什么区别?
What difference between passing an instance and a brace-enclosed initializer list to a function?
假设我有以下代码。
class A
{
public:
float x, y, z;
A(float x, float y, float z) : x(x), y(y), z(z) {}
};
float average(A a)
{
return (a.x + a.y + a.z) / 3;
}
这两种方式调用函数有什么实际区别吗?
// a)
average(A(1, 2, 3))
// b)
average({1, 2, 3})
这取决于您使用的 C++ 版本。
从 copy elision @ cpprefrence 复制(并略微修改)(因此,不是准确引用):
In C++17 core language specification of prvalues
and temporaries is fundamentally different from that of the earlier C++ revisions: there is no longer a temporary to copy/move from.
这意味着您在 average(A(1, 2, 3))
中直观显示的临时 A
自 C++17 起不允许复制或移动。其实暂时没有。在 C++17 之前,大多数编译器使用 copy (and move) elision (这在早些时候也被允许,但不是强制性的)达到同样的效果——但你不能移植靠。
在 C++17 中,这种形式的 复制省略 是强制性的,因此称为 Return 值优化 ,或简称 RVO。您还将阅读有关 Named RVO(或 NRVO)的内容,它们很相似,但不遵循相同的规则。它有点复杂,超出了这个答案的范围。
在 C++17 之前,average(A(1, 2, 3))
实际上可能意味着创建 A
的临时实例并且 move 或 copy 函数中 A
的构造函数必须移动(或对于 non-movable,复制)临时资源 - 这通常很便宜,但没有是 - 它可能会带来副作用。
有些类型既不可复制也不可移动。在这种情况下,调用在 C++17 之前是无效的。在 C++17 中,delete
d move 和 copy 构造函数在这种情况下无关紧要,因为没有要移动或移动的实例复制自 - 并且调用 是 因此无疑是有效的。
当使用大括号括起来的初始化列表时,正如您在本例中所做的那样,甚至不允许 C++11 创建(和移动)A
的临时实例。这些值直接传递给 A(float x, float y, float z)
.
中的构造函数
除此之外,我看不出你的例子有什么不同。
假设我有以下代码。
class A
{
public:
float x, y, z;
A(float x, float y, float z) : x(x), y(y), z(z) {}
};
float average(A a)
{
return (a.x + a.y + a.z) / 3;
}
这两种方式调用函数有什么实际区别吗?
// a)
average(A(1, 2, 3))
// b)
average({1, 2, 3})
这取决于您使用的 C++ 版本。
从 copy elision @ cpprefrence 复制(并略微修改)(因此,不是准确引用):
In C++17 core language specification of
prvalues
and temporaries is fundamentally different from that of the earlier C++ revisions: there is no longer a temporary to copy/move from.
这意味着您在 average(A(1, 2, 3))
中直观显示的临时 A
自 C++17 起不允许复制或移动。其实暂时没有。在 C++17 之前,大多数编译器使用 copy (and move) elision (这在早些时候也被允许,但不是强制性的)达到同样的效果——但你不能移植靠。
在 C++17 中,这种形式的 复制省略 是强制性的,因此称为 Return 值优化 ,或简称 RVO。您还将阅读有关 Named RVO(或 NRVO)的内容,它们很相似,但不遵循相同的规则。它有点复杂,超出了这个答案的范围。
在 C++17 之前,average(A(1, 2, 3))
实际上可能意味着创建 A
的临时实例并且 move 或 copy 函数中 A
的构造函数必须移动(或对于 non-movable,复制)临时资源 - 这通常很便宜,但没有是 - 它可能会带来副作用。
有些类型既不可复制也不可移动。在这种情况下,调用在 C++17 之前是无效的。在 C++17 中,delete
d move 和 copy 构造函数在这种情况下无关紧要,因为没有要移动或移动的实例复制自 - 并且调用 是 因此无疑是有效的。
当使用大括号括起来的初始化列表时,正如您在本例中所做的那样,甚至不允许 C++11 创建(和移动)A
的临时实例。这些值直接传递给 A(float x, float y, float z)
.
除此之外,我看不出你的例子有什么不同。