[英]C++,class, a function that returns an object
我写了一个名为Point
的 Class 并想写一个 function 需要 2 个Points
并将它们相加。
为什么我应该写如下:
Point SumPoints(Point& p1, Point& p2)
{
Point result(p1->x + p2->x, p1->y + p2->y);
return result;
}
为结果定义一个指针并返回它不是更有效吗? (而不是定义一个新的 Point 'result' 然后在 main 中再次复制它)
另外,当自动调用副本 function 时,我有点困惑? 每当我输入=
时它都会被调用,这是真的吗?
在这里,按值返回result
是完全有效的。 现代编译器将应用 NRVO命名的返回值优化,这样就不需要复制。 如果一个指针由 sum 操作返回,那会更加混乱。
关于您的其他问题(如果我理解正确的话),使用=
并不总是涉及复制。 例如,还有一个移动赋值运算符,它只是将rvalue
引用移动到 object 中,而不是复制它。 也有应用复制省略的情况(与上面相同的链接)并允许完全避免复制和移动语义。
在以下示例中,您可以看到编译器大部分都省略了复制或移动(现场演示)
#include <string>
#include <iostream>
#include <iomanip>
struct Point{
Point() = default;
Point(double x, double y):x(x),y(y){}
Point(const Point &p):x(p.x),y(p.y){
std::cout << "copy construct" << std::endl;}
Point(Point&& p):x(std::move(p.x)),y(std::move(p.y)){
std::cout << "move construct" << std::endl;}
Point& operator=(const Point& p){
x = p.x;
y = p.y;
std::cout << "copy assign" << std::endl;
return *this;
}
Point& operator=(Point&& p){
x = std::move(p.x);
y = std::move(p.y);
std::cout << "move assign" << std::endl;
return *this;
}
double x,y;
};
std::ostream& operator<<(std::ostream& out, const Point& p)
{
out << std::setw(5) << p.x << std::setw(5) << p.x << std::flush;
return out;
}
Point operator+(const Point& p1, const Point &p2)
{
return Point(p1.x+p2.x,p1.y+p2.y);
}
Point sum1(const Point& p1, const Point &p2)
{
return Point(p1.x+p2.x,p1.y+p2.y);
}
Point sum2(const Point& p1, const Point &p2)
{
Point result;
result.x = p1.x+p2.x;
result.y = p1.y+p2.y;
return result;
}
int main()
{
Point p1(1,0), p2(0,1);
auto r1 = sum2(p1,p2);
auto r2 = sum1(p1,p2);
auto r3 = r1+r2;
auto r4 = r3; // <- only this calls the copy constructor
std::cout << "r3 = ("<< r3 << ")"<< std::endl;
}
这打印:
copy construct
r3 = ( 2 2)
作为提示,您可以重载+
运算符,如示例中所示,以更易读的方式编写总和。
为结果定义一个指针并返回它不是更有效吗?
如果您不创建 object,那么指针将不会指向任何内容。
从加法运算符返回指针也将是高度混乱和非常规的。
然后在 main 中再次复制它
如果优化器设法省略了副本,它就不一定会被复制。
如果您使用结果而不是分配来初始化 object,则可以通过返回纯右值来确保不会有副本:
return Point(p1->x + p2->x, p1->y + p2->y);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.