Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

วิธี Return Object จากฟังก์ชันใน C++

ภาพรวม

ใน C++ สามารถ Return Object จากฟังก์ชันได้หลายวิธี แต่ละวิธีมีข้อดี/ข้อเสียต่างกัน สมัยใหม่ (C++11+) ใช้ Return by Value ร่วมกับ Move Semantics และ NRVO (Named Return Value Optimization) เป็นหลัก

วิธีต่างๆ ในการ Return Object

1. Return by Value (Modern C++ - แนะนำ)


#include <iostream>
using namespace std;

class Point {
    int x, y;
public:
    Point(int x1 = 0, int y1 = 0) : x(x1), y(y1) {}
    
    Point addPoint(const Point& p) const {
        Point temp;           // Local Object
        temp.x = x + p.x;
        temp.y = y + p.y;
        return temp;          // Return by Value
    }
    
    void display() const {
        cout << "x = " << x << "\ny = " << y << "\n";
    }
};

int main() {
    Point p1(5, 3), p2(12, 6);
    Point p3 = p1.addPoint(p2);  // NRVO: No Copy/Move!
    p3.display();
    return 0;
}

2. Return by Reference (สำหรับ Existing Object)


Point& getOrigin() {
    static Point origin(0, 0);  // Static: Lifetime = Program
    return origin;              // Safe: Object ยังอยู่
}

// ใช้กับ Operator Overloading
Point& Point::operator+=(const Point& other) {
    x += other.x;
    y += other.y;
    return *this;  // Return Reference to Self
}

3. Return by Pointer (Legacy / Optional)


// Factory Pattern
unique_ptr createPoint(int x, int y) {
    return make_unique(x, y);  // Smart Pointer - Safe
}

// Optional Return (C++17)
#include <optional>
optional findPoint(int id) {
    if (id > 0) return Point(id, id);
    return nullopt;  // No Value
}

โค้ดตัวอย่างครบถ้วน (จากต้นฉบับ + ปรับปรุง)


#include <iostream>
using namespace std;

class Point {
    int x, y;
public:
    Point(int x1 = 0, int y1 = 0) : x(x1), y(y1) {}
    
    // Return by Value - Best for C++17+
    Point addPoint(const Point& p) const {
        return Point(x + p.x, y + p.y);  // Direct Return - NRVO Guaranteed
    }
    
    void display() const {
        cout << "x = " << x << "\ny = " << y << "\n";
    }
};

int main() {
    Point p1(5, 3);
    Point p2(12, 6);
    
    cout << "Point 1\n";
    p1.display();
    
    cout << "Point 2\n";
    p2.display();
    
    Point p3 = p1.addPoint(p2);
    cout << "The sum of the two points is:\n";
    p3.display();
    
    return 0;
}

ผลลัพธ์


Point 1
x = 5
y = 3
Point 2
x = 12
y = 6
The sum of the two points is:
x = 17
y = 9

Copy/Move Elision (Optimization)

Best Practices (C++17+)

  1. Default: Return by Value - ให้ Compiler Optimize (NRVO)
  2. Polymorphism/Optional: std::unique_ptr, std::optional, std::variant
  3. Large Objects / Non-movable: Pass Output Parameter หรือ std::unique_ptr
  4. Reference: เฉพาะ Static/Global/Existing Object (ไม่ใช่ Local!)

สิ่งที่ห้ามทำ


// ❌ Dangerous: Return Reference to Local
Point& badAdd(const Point& p) {
    Point temp;  // Local!
    temp.x = x + p.x;
    return temp;  // Dangling Reference! UB!
}

// ❌ Dangerous: Return Pointer to Local
Point* badAddPtr(const Point& p) {
    Point temp;
    return &temp;  // Dangling Pointer! UB!
}
StandardBehavior
C++98/03Copy Elision: Allowed (Optional) - Compiler อาจ Optimize
C++11Move Semantics: Return by Value ใช้ Move Constructor
C++17Guaranteed NRVO/RVO: ห้าม Copy/Move สร้าง Object โดยตรงใน Caller