0Pricing
C++ Academy · บทเรียน

std::function

จัดเก็บสิ่งที่เรียกใช้งานได้ทุกชนิด

std::function เป็นบทเรียน C++ Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C++ Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C++ Academy มีบทเรียนทั้งหมด 4 บทเรียน

std::function คืออะไร

std::function เป็นตัวห่อหุ้มที่ลบชนิด ซึ่งสามารถเก็บสิ่งที่เรียกใช้งานได้ทุกชนิดที่ตรงกับลายเซ็นที่กำหนด ไม่ว่าจะเป็นฟังก์ชันอิสระ แลมบ์ดา ฟังก์เตอร์ หรือ นิพจน์ที่ผูกไว้

  • ประกาศด้วยลายเซ็นเป้าหมาย
  • อยู่ใน <functional>
#include <iostream>
#include <functional>

int add(int a, int b) { return a + b; }

int main() {
    std::function<int(int, int)> f = add;
    std::cout << f(2, 3) << '\n';
    return 0;
}

การเก็บแลมบ์ดา

ต่างจากพอยน์เตอร์ฟังก์ชันแบบดิบตรงที่ std::function สามารถเก็บแลมบ์ดาได้อย่างสะดวก แม้แต่แลมบ์ดาที่มีการจับค่าก็ตาม

#include <iostream>
#include <functional>

int main() {
    int offset = 10;
    std::function<int(int)> f = [offset](int x) { return x + offset; };
    std::cout << f(5) << '\n';
    return 0;
}

การเก็บฟังก์เตอร์

ฟังก์เตอร์คือออบเจ็กต์ที่มี operator() std::function สามารถห่อหุ้มฟังก์เตอร์ไว้ และเรียกใช้ตัวดำเนินการของฟังก์เตอร์เมื่อถูกเรียก

#include <iostream>
#include <functional>

struct Multiplier {
    int factor;
    int operator()(int x) const { return x * factor; }
};

int main() {
    std::function<int(int)> f = Multiplier{3};
    std::cout << f(4) << '\n';
    return 0;
}

การกำหนดเป้าหมายใหม่

ตัวแปร std::function หนึ่งตัวสามารถชี้ไปยังสิ่งที่เรียกใช้งานได้แตกต่างกันตลอดอายุการใช้งานของตัวแปร ซึ่งมีประโยชน์สำหรับการสลับพฤติกรรมขณะทำงาน

#include <iostream>
#include <functional>

int main() {
    std::function<int(int)> f = [](int x) { return x + 1; };
    std::cout << f(10) << '\n';
    f = [](int x) { return x * x; };
    std::cout << f(10) << '\n';
    return 0;
}

std::function ว่าง

std::function ที่สร้างด้วยค่าเริ่มต้นจะไม่เก็บสิ่งใดไว้ การเรียกใช้จะส่งข้อยกเว้น std::bad_function_call ดังนั้นโปรดทดสอบก่อน

#include <iostream>
#include <functional>

int main() {
    std::function<void()> f;
    if (f) {
        f();
    } else {
        std::cout << "empty\n";
    }
    return 0;
}

ในฐานะพารามิเตอร์

ฟังก์ชันสามารถรับพารามิเตอร์ std::function เพื่อรับสิ่งที่เรียกใช้งานได้ชนิดใดก็ได้ที่ตรงกัน ทำให้ส่วนเชื่อมต่อการเขียนโปรแกรมมีความยืดหยุ่น

#include <iostream>
#include <functional>

void repeat(int n, const std::function<void(int)>& action) {
    for (int i = 0; i < n; ++i) action(i);
}

int main() {
    repeat(3, [](int i) { std::cout << "step " << i << '\n'; });
    return 0;
}

การเก็บการเรียกกลับ

การใช้งานที่พบได้ทั่วไปคือเก็บการเรียกกลับไว้ในสมาชิกของคลาส เพื่อให้เรียกใช้ภายหลังเมื่อเกิดเหตุการณ์ขึ้น

#include <iostream>
#include <functional>

struct Button {
    std::function<void()> onClick;
    void click() { if (onClick) onClick(); }
};

int main() {
    Button b;
    b.onClick = [] { std::cout << "clicked!\n"; };
    b.click();
    return 0;
}

เวกเตอร์ของสิ่งที่เรียกใช้งานได้

เนื่องจากสิ่งเหล่านี้มีชนิดเดียวกัน สิ่งที่เรียกใช้งานได้หลายรูปแบบจึงอยู่ร่วมกันในคอนเทนเนอร์และถูกเรียกใช้ทีละตัวได้

#include <iostream>
#include <functional>
#include <vector>

int inc(int x) { return x + 1; }

int main() {
    std::vector<std::function<int(int)>> ops;
    ops.push_back(inc);
    ops.push_back([](int x) { return x * 2; });
    for (auto& op : ops) std::cout << op(10) << ' ';
    std::cout << '\n';
    return 0;
}

ต้นทุนของการลบชนิด

std::function อาจจัดสรรหน่วยความจำและเพิ่มการเรียกใช้ทางอ้อม จึงช้ากว่าการเรียกใช้โดยตรงหรือสิ่งที่เรียกใช้งานได้จากแม่แบบเล็กน้อย โปรดใช้เมื่อคุณต้องการเก็บสิ่งเหล่านี้ด้วยชนิดเดียวกัน

#include <iostream>
#include <functional>

int main() {
    std::function<int()> f = [] { return 42; };
    int total = 0;
    for (int i = 0; i < 5; ++i) total += f();
    std::cout << total << '\n';
    return 0;
}

การส่งคืน std::function

โรงงานสามารถสร้างและส่งคืนสิ่งที่เรียกใช้งานได้ซึ่งกำหนดค่าไว้แล้ว ทำให้ผู้เรียกได้รับพฤติกรรมที่ปรับแต่งได้

#include <iostream>
#include <functional>

std::function<int(int)> adder(int n) {
    return [n](int x) { return x + n; };
}

int main() {
    auto add5 = adder(5);
    std::cout << add5(10) << '\n';
    return 0;
}

การเปรียบเทียบกับพอยน์เตอร์ฟังก์ชัน

std::function ยืดหยุ่นกว่าพอยน์เตอร์ฟังก์ชัน เพราะสามารถเก็บสถานะได้ แต่ความยืดหยุ่นนี้แลกมาด้วยประสิทธิภาพที่ลดลงเล็กน้อยและอาจมีการจัดสรรหน่วยความจำ

#include <iostream>
#include <functional>

int main() {
    int base = 7;
    std::function<int(int)> stateful = [base](int x) { return x + base; };
    std::cout << "Stateful result: " << stateful(3) << '\n';
    return 0;
}

ตรวจสอบอย่างรวดเร็ว

ทดสอบความเข้าใจของคุณเกี่ยวกับ std::function

สรุปทบทวน

คุณได้เรียนรู้ว่า std::function:

  • ห่อหุ้มสิ่งที่เรียกใช้งานได้ทุกชนิดที่ตรงกับลายเซ็น รวมถึงแลมบ์ดาและฟังก์เตอร์ที่มีสถานะ
  • สามารถกำหนดค่าใหม่ เก็บไว้ในคอนเทนเนอร์ และส่งคืนจากโรงงานได้
  • ส่งข้อยกเว้น bad_function_call เมื่อไม่มีสิ่งใดอยู่ภายใน
  • มีค่าใช้จ่ายเพิ่มเติมเล็กน้อยจากการลบชนิด

ถัดไป คุณจะใช้ std::bind เพื่อเติมอาร์กิวเมนต์ล่วงหน้าให้สิ่งที่เรียกใช้งานได้

คำถามที่พบบ่อย

บทเรียน “std::function” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “std::function” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C++ Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C++ Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “std::function”

จัดเก็บสิ่งที่เรียกใช้งานได้ทุกชนิด คุณปฏิบัติ C++ Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C++ Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน C++ Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “std::function” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน C++ Academy นี้ได้ไหม

ได้ บทเรียน C++ Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. พอยน์เตอร์ฟังก์ชัน
  2. std::function
  3. std::bind
  4. การเลือกสิ่งที่เรียกใช้งานได้
← กลับไปที่ C++ Academy