繁体   English   中英

C++,class,一个 function 返回一个 ZA8CFDE6331BD59EB2AC96F8911C4B666

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM