首页 > 解决方案 > C++,class,一个返回对象的函数

问题描述

我写了一个名为的类Point,并想编写一个接受 2Points并对它们求和的函数。

为什么我应该写如下:

Point SumPoints(Point& p1, Point& p2)
{
    Point result(p1->x + p2->x, p1->y + p2->y);
    return result;
}

为结果定义一个指针并返回它不是更有效吗?(而不是定义一个新的 Point 'result' 然后在 main 中再次复制它)

另外,我对何时自动调用复制功能有点困惑?每当我输入=它就会被调用,这是真的吗?

标签: c++functionclass

解决方案


result在这里,按值返回是完全有效的。现代编译器将应用 NRVO命名的返回值优化,这样就不需要复制。如果一个指针由 sum 操作返回,那会更加混乱。

关于您的其他问题(如果我理解正确的话),使用=并不总是涉及复制。例如,还有一个移动赋值运算符,它只是将rvalue引用移动到对象中而不是复制它。也有应用复制省略的情况(与上面相同的链接)并允许完全避免复制和移动语义。

在以下示例中,您可以看到编译器大部分都省略了复制或移动(现场演示

#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)

作为提示,您可以重载+示例中所示的运算符,以便以更易读的方式编写总和。


推荐阅读