ความสำคัญของ ios_base :: sync_with_stdio (false); cin.tie (NULL);


146

ความสำคัญของการรวมคืออะไร

ios_base::sync_with_stdio(false);
cin.tie(NULL);

ในโปรแกรม C ++?

ในการทดสอบของฉันมันเร็วขึ้นเวลาดำเนินการ แต่มีกรณีทดสอบที่ฉันควรกังวลเกี่ยวกับการรวมนี้

คำแถลง 2 ต้องอยู่ด้วยกันเสมอหรือเป็นคำแรกที่เพียงพอเช่นเพิกเฉยcin.tie(NULL)?

นอกจากนี้ยังอนุญาตให้ใช้คำสั่ง C และ C ++ พร้อมกันได้falseหรือไม่หากค่าถูกตั้งเป็น?

https://www.codechef.com/viewsolution/7316085

รหัสข้างต้นทำงานดีจนผมใช้scanf/printfใน C ++ trueโปรแกรมที่มีค่าเป็น ในกรณีนี้มันทำให้เกิดความผิดพลาดในการแบ่งส่วน อะไรคือคำอธิบายที่เป็นไปได้สำหรับสิ่งนี้


คุณใช้มันด้วยความจริง รหัสของคุณพูดอย่างนั้น ???
Suraj Jain

คำตอบ:


231

การเรียกทั้งสองมีความหมายต่างกันซึ่งไม่เกี่ยวข้องกับประสิทธิภาพ ความจริงที่ว่ามันเพิ่มความเร็วเวลาการดำเนินการเป็น (หรืออาจจะ ) เพียงผลข้างเคียง คุณควรเข้าใจสิ่งที่แต่ละคนทำและไม่รวมในทุก ๆ โปรแกรมเพราะพวกเขาดูเหมือนการเพิ่มประสิทธิภาพ

ios_base::sync_with_stdio(false);

สิ่งนี้จะปิดใช้งานการซิงโครไนซ์ระหว่างสตรีมมาตรฐาน C และ C ++ โดยค่าเริ่มต้นสตรีมมาตรฐานทั้งหมดจะถูกซิงโครไนซ์ซึ่งในทางปฏิบัติอนุญาตให้คุณผสม C- และ C ++ - สไตล์ I / O และรับผลลัพธ์ที่สมเหตุสมผลและคาดหวัง หากคุณปิดใช้งานการซิงโครไนซ์สตรีม C ++ จะได้รับอนุญาตให้มีบัฟเฟอร์อิสระของตัวเองซึ่งจะทำให้การมิกซ์ C- และ C ++ - สไตล์ I / O เป็นการผจญภัย

โปรดทราบว่าสตรีม C ++ ที่ซิงโครไนซ์นั้นมีความปลอดภัยต่อเธรด (เอาต์พุตจากเธรดที่แตกต่างกันอาจสอดแทรก แต่คุณไม่ได้รับข้อมูลซ้ำ)

cin.tie(NULL);

ปลดนี้จากcin coutสตรีมที่เชื่อมโยงจะตรวจสอบให้แน่ใจว่าสตรีมหนึ่งรายการถูกล้างข้อมูลโดยอัตโนมัติก่อนการดำเนินการ I / O แต่ละครั้งบนสตรีมอื่น

โดยค่าเริ่มต้นcinจะเชื่อมโยงกับcoutเพื่อให้แน่ใจว่ามีการโต้ตอบกับผู้ใช้ที่เหมาะสม ตัวอย่างเช่น:

std::cout << "Enter name:";
std::cin >> name;

หากcinและcoutเชื่อมโยงกันคุณสามารถคาดหวังได้ว่าเอาต์พุตจะถูกฟลัช (เช่นมองเห็นได้บนคอนโซล) ก่อนที่โปรแกรมจะพร้อมต์อินพุตจากผู้ใช้ หากคุณแก้กระแสข้อมูลโปรแกรมอาจบล็อกการรอให้ผู้ใช้ป้อนชื่อ แต่ข้อความ "ป้อนชื่อ" ยังไม่ปรากฏ (เนื่องจากcoutบัฟเฟอร์โดยค่าเริ่มต้นเอาต์พุตจะถูกล้างออก / แสดงบนคอนโซลตามต้องการเท่านั้นหรือเมื่อ บัฟเฟอร์เต็ม)

ดังนั้นถ้าคุณแก้cinจากcoutคุณต้องให้แน่ใจว่าจะล้างด้วยตนเองเวลาที่คุณต้องการบางสิ่งบางอย่างแสดงผลทุกครั้งก่อนคาดหวังว่าข้อมูลเกี่ยวกับcoutcin

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


เมื่อคุณพูดว่า "คุณต้องแน่ใจว่าจะล้าง cout ด้วยตนเองทุกครั้งที่คุณต้องการแสดงอะไรบางอย่างก่อนที่จะคาดหวังอินพุตใน cin" ซึ่งอาจเป็นเรื่องง่ายเหมือนกับการต่อท้าย "... << std :: flush" หรือ "... < <std :: endl "ถึงท้ายทุกบรรทัดที่เริ่มต้น" std :: cout << ... "ใช่ไหม
Alan

4
ใช่มันง่ายอย่างนั้น แต่ระวังด้วย "ส่วนท้ายของทุกบรรทัด" coutถูกบัฟเฟอร์ด้วยเหตุผลหากคุณล้างข้อมูลบ่อยเกินไปเมื่อคุณไม่ต้องการใช้งานจริงคุณอาจเห็นการแสดงที่มีประสิทธิภาพ
Ionut

@Ionut มีบางอย่างที่เทียบเท่ากับฟังก์ชัน tie () ใน C สำหรับ scanf, printf หรือไม่
iajnr

1
@iajnr ไม่ไม่โดยตรง ใน C คุณสามารถล้างข้อมูลด้วยตนเองก่อนscanf()ปิดใช้งานการบัฟเฟอร์อย่างสมบูรณ์หรือสลับไปที่การบัฟเฟอร์บรรทัด (ซึ่งควรล้างข้อมูลหลังจากบรรทัดใหม่หรือเมื่ออ่านอินพุตstdin- ดูlinux.die.net/man/3/setlinebuf )
Ionut

1
ที่ leetcode มันปรับปรุงการรันไทม์อย่างมีนัยสำคัญบางทีเว็บไซต์ที่มีการแข่งขันเหล่านี้อาจทำสิ่งพิเศษสำหรับการทดสอบอินพุต
P0W

18

นี่คือการซิงโครไนซ์ IO จากโลก C และ C ++ หากคุณซิงโครไนซ์แสดงว่าคุณมีการรับประกันว่าคำสั่งซื้อของ IO ทั้งหมดเป็นสิ่งที่คุณคาดหวัง โดยทั่วไปปัญหาคือบัฟเฟอร์ของ IO ที่ทำให้เกิดปัญหาการซิงโครไนซ์ให้ทั้งสองโลกแบ่งปันบัฟเฟอร์เดียวกัน ยกตัวอย่างเช่นcout << "Hello"; printf("World"); cout << "Ciao";; คุณจะไม่มีทางรู้ได้เลยว่าคุณจะได้HelloCiaoWorldหรือHelloWorldCiaoหรือWorldHelloCiao...

tieช่วยให้คุณรับประกันได้ว่าช่องทาง IOs ใน C ++ world เชื่อมโยงกันซึ่งหมายความว่าตัวอย่างเช่นทุกเอาต์พุตถูกล้างออกก่อนที่อินพุตจะเกิดขึ้น (ลองคิดดูcout << "What's your name ?"; cin >> name;)

คุณสามารถผสม C หรือ C ++ IO ได้ตลอดเวลา แต่หากคุณต้องการพฤติกรรมที่เหมาะสมคุณต้องซิงโครไนซ์ทั้งสองโลก ระวังว่าโดยทั่วไปจะไม่แนะนำให้ผสมพวกเขาถ้าคุณโปรแกรมใน C ใช้ C stdio และถ้าคุณโปรแกรมใน C ++ ใช้กระแสข้อมูล แต่คุณอาจต้องการผสมไลบรารี C ที่มีอยู่เป็นรหัส C ++ และในกรณีเช่นนี้จำเป็นต้องซิงโครไนซ์ทั้งคู่


4
แม้จะไม่มีการซิงโครไนซ์การโทรที่แตกต่างไปcout <<ยังไม่สามารถเปลี่ยนลำดับได้จึงCiaoHelloWorldเป็นไปไม่ได้สำหรับกรณีตัวอย่างของคุณ การทำข้อมูลให้ตรงกันเป็นเรื่องเกี่ยวกับวิธีการบัฟเฟอร์ที่แตกต่างกันอย่างเคร่งครัด
Mikko Rantalainen

3

การใช้ios_base::sync_with_stdio(false);มีความเพียงพอในการแยกCและC++ลำธาร คุณสามารถค้นหาการสนทนานี้ในมาตรฐาน C ++ IOStreams and Localesโดย Langer และ Kreft พวกเขาทราบว่าการทำงานนี้ถูกกำหนดโดยการนำไปใช้งาน

cin.tie(NULL)โทรดูเหมือนว่าจะขอ decoupling ระหว่างกิจกรรมบนและcin coutฉันไม่สามารถอธิบายได้ว่าทำไมการใช้สิ่งนี้กับการเพิ่มประสิทธิภาพอื่น ๆ จึงทำให้เกิดความผิดพลาด ตามที่ระบุไว้ลิงก์ที่คุณให้มาไม่ดีดังนั้นจึงไม่มีการเก็งกำไรที่นี่


0

มันเป็นเรื่องธรรมดาที่ทำให้cin input ทำงานได้เร็วขึ้น

สำหรับคำอธิบายอย่างรวดเร็ว: บรรทัดแรกจะปิดการซิงโครไนซ์บัฟเฟอร์ระหว่างcin stream และเครื่องมือstdio ในสไตล์ C (เช่น scanf หรือรับ) - ดังนั้นcinจึงทำงานได้เร็วขึ้น แต่คุณไม่สามารถใช้พร้อมกันได้กับเครื่องมือstdio

ปลดบรรทัดที่สองCINจากศาล - โดยเริ่มต้นศาลบัฟเฟอร์วูบวาบในแต่ละครั้งเมื่อคุณอ่านอะไรบางอย่างจากCIN และอาจช้าเมื่อคุณอ่านสิ่งเล็ก ๆ ซ้ำ ๆ จากนั้นเขียนบางสิ่งเล็ก ๆ หลาย ๆ ครั้ง ดังนั้นบรรทัดจะปิดการซิงโครไนซ์นี้ (โดยการผูกcinเป็นโมฆะแทนcout )

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.