มีเอกสารใดบ้างที่เปรียบเทียบ / เปรียบเทียบการปรับใช้มาตรฐานไลบรารี C ++ [ปิด]


16

(นี่ไม่ใช่การเขียนโปรแกรมเกมต่อ แต่ฉันแน่ใจว่าฉันถามเรื่องนี้ดังนั้นฉันจะได้รับการบอกว่าจะไม่ปรับให้เหมาะสมก่อนที่จะถึงแม้ว่าประวัติศาสตร์บอกเราทุกเกมใหญ่จบลงด้วยความกังวลเกี่ยวกับสิ่งเหล่านี้.)

มีเอกสารใดบ้างที่สรุปความแตกต่างของประสิทธิภาพและโดยเฉพาะอย่างยิ่งการใช้หน่วยความจำระหว่างการใช้งานไลบรารีมาตรฐาน C ++ แตกต่างกันหรือไม่? รายละเอียดของการใช้งานบางอย่างได้รับการคุ้มครองโดย NDA แต่การเปรียบเทียบระหว่าง STLport กับ libstdc ++ เทียบกับ libc ++ กับ MSVC / Dinkumware (เทียบกับ EASTL?) ดูเหมือนว่าจะมีประโยชน์อย่างมาก

โดยเฉพาะฉันกำลังมองหาคำตอบสำหรับคำถามที่ชอบ:

  • หน่วยความจำค่าใช้จ่ายเกี่ยวข้องกับคอนเทนเนอร์มาตรฐานเท่าไร?
  • คอนเทนเนอร์ใดมีถ้าทำการจัดสรรแบบไดนามิกโดยการประกาศเท่านั้น
  • std :: string ทำการคัดลอกเมื่อเขียนหรือไม่? การเพิ่มประสิทธิภาพสตริงสั้น ๆ ? เชือก?
  • std :: deque ใช้บัฟเฟอร์วงแหวนหรือไม่?

ฉันอยู่ภายใต้การแสดงผลที่dequeมีการนำไปใช้เสมอใน STL ด้วยเวกเตอร์
Tetrad

@ Tetrad: จนกระทั่งไม่กี่สัปดาห์ที่ผ่านมาฉันก็เหมือนกัน แต่แล้วฉันก็อ่านมันมักจะถูกนำมาใช้โดยโครงสร้างเหมือนเชือก - และดูเหมือนว่าจะเป็นสิ่งที่อยู่ใน STLport

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

3
@Duck: การพัฒนาเกมเป็นที่เดียวที่ฉันรู้ว่าใช้คุณสมบัติ C ++ ระดับสูงเป็นประจำ แต่ต้องติดตามการจัดสรรหน่วยความจำอย่างพิถีพิถันเพราะมันทำงานบนระบบที่ไม่มีหน่วยความจำเสมือนไม่มีหน่วยความจำต่ำ ทุกคำตอบเดียวของ SO ก็คือ "อย่าปรับให้เหมาะสมก่อนเวลาอันควร STL นั้นใช้ได้เลย!" - 50% ของคำตอบที่นี่จนถึงตอนนี้ - และยังทดสอบของ Maik แสดงให้เห็นชัดเจนว่าเป็นข้อกังวลสำคัญสำหรับเกมที่ต้องการใช้ std :: map และความสับสนของ Tetrad และระเบิดเกี่ยวกับ std :: deque implementations ทั่วไป

2
@Joe Wreschnig ฉันไม่ต้องการลงคะแนนให้ปิดเพราะฉันสนใจผลลัพธ์ของสิ่งนี้ : p
The Duck Communist

คำตอบ:


6

ในกรณีที่คุณไม่พบแผนภูมิเปรียบเทียบทางเลือกอื่นคือการฉีดตัวจัดสรรของตัวเองไปยังคลาส STL ที่มีปัญหาและเพิ่มการบันทึกบางส่วน

การใช้งานที่ฉันทดสอบ (VC 8.0) ไม่ใช้การจัดสรรหน่วยความจำเพียงแค่ประกาศสตริง / vector / deque แต่สำหรับรายการและแผนที่ สตริงมีการเพิ่มประสิทธิภาพสตริงแบบสั้นเนื่องจากการเพิ่ม 3 ตัวอักษรไม่ทำให้เกิดการจัดสรร เอาท์พุทจะถูกเพิ่มด้านล่างรหัส

// basic allocator implementation used from here
// http://www.codeguru.com/cpp/cpp/cpp_mfc/stl/article.php/c4079

#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <map>

template <class T> class my_allocator;

// specialize for void:
template <> 
class my_allocator<void> 
{
public:
    typedef void*       pointer;
    typedef const void* const_pointer;
    // reference to void members are impossible.
    typedef void value_type;
    template <class U> 
    struct rebind 
    { 
        typedef my_allocator<U> other; 
    };
};

#define LOG_ALLOC_SIZE(call, size)      std::cout << "  " << call << "  " << std::setw(2) << size << " byte" << std::endl

template <class T> 
class my_allocator 
{
public:
    typedef size_t    size_type;
    typedef ptrdiff_t difference_type;
    typedef T*        pointer;
    typedef const T*  const_pointer;
    typedef T&        reference;
    typedef const T&  const_reference;
    typedef T         value_type;
    template <class U> 
    struct rebind 
    { 
        typedef my_allocator<U> other; 
    };

    my_allocator() throw() : alloc() {}
    my_allocator(const my_allocator&b) throw() : alloc(b.alloc) {}

    template <class U> my_allocator(const my_allocator<U>&b) throw() : alloc(b.alloc) {}
    ~my_allocator() throw() {}

    pointer       address(reference x) const                    { return alloc.address(x); }
    const_pointer address(const_reference x) const              { return alloc.address(x); }

    pointer allocate(size_type s, 
               my_allocator<void>::const_pointer hint = 0)      { LOG_ALLOC_SIZE("my_allocator::allocate  ", s * sizeof(T)); return alloc.allocate(s, hint); }
    void deallocate(pointer p, size_type n)                     { LOG_ALLOC_SIZE("my_allocator::deallocate", n * sizeof(T)); alloc.deallocate(p, n); }

    size_type max_size() const throw()                          { return alloc.max_size(); }

    void construct(pointer p, const T& val)                     { alloc.construct(p, val); }
    void destroy(pointer p)                                     { alloc.destroy(p); }

    std::allocator<T> alloc;
};

int main(int argc, char *argv[])
{

    {
        typedef std::basic_string<char, std::char_traits<char>, my_allocator<char> > my_string;

        std::cout << "===============================================" << std::endl;
        std::cout << "my_string ctor start" << std::endl;
        my_string test;
        std::cout << "my_string ctor end" << std::endl;
        std::cout << "my_string add 3 chars" << std::endl;
        test = "abc";
        std::cout << "my_string add a huge number of chars chars" << std::endl;
        test += "d df uodfug ondusgp idugnösndögs ifdögsdoiug ösodifugnösdiuödofu odsugöodiu niu od unoudö n nodsu nosfdi un abc";
        std::cout << "my_string copy" << std::endl;
        my_string copy = test;
        std::cout << "my_string copy on write test" << std::endl;
        copy[3] = 'X';
        std::cout << "my_string dtors start" << std::endl;
    }

    {
        std::cout << std::endl << "===============================================" << std::endl;
        std::cout << "vector ctor start" << std::endl;
        std::vector<int, my_allocator<int> > v;
        std::cout << "vector ctor end" << std::endl;
        for(int i = 0; i < 5; ++i)
        {
            v.push_back(i);
        }
        std::cout << "vector dtor starts" << std::endl;
    }

    {
        std::cout << std::endl << "===============================================" << std::endl;
        std::cout << "deque ctor start" << std::endl;
        std::deque<int, my_allocator<int> > d;
        std::cout << "deque ctor end" << std::endl;
        for(int i = 0; i < 5; ++i)
        {
            std::cout << "deque insert start" << std::endl;
            d.push_back(i);
            std::cout << "deque insert end" << std::endl;
        }
        std::cout << "deque dtor starts" << std::endl;
    }

    {
        std::cout << std::endl << "===============================================" << std::endl;
        std::cout << "list ctor start" << std::endl;
        std::list<int, my_allocator<int> > l;
        std::cout << "list ctor end" << std::endl;
        for(int i = 0; i < 5; ++i)
        {
            std::cout << "list insert start" << std::endl;
            l.push_back(i);
            std::cout << "list insert end" << std::endl;
        }
        std::cout << "list dtor starts" << std::endl;
    }

    {
        std::cout << std::endl << "===============================================" << std::endl;
        std::cout << "map ctor start" << std::endl;
        std::map<int, float, std::less<int>, my_allocator<std::pair<const int, float> > > m;
        std::cout << "map ctor end" << std::endl;
        for(int i = 0; i < 5; ++i)
        {
            std::cout << "map insert start" << std::endl;
            std::pair<int, float> a(i, (float)i);
            m.insert(a);
            std::cout << "map insert end" << std::endl;
        }
        std::cout << "map dtor starts" << std::endl;
    }

    return 0;
}

จนถึง VC8 และ STLPort 5.2 ที่ทดสอบแล้วนี่คือการเปรียบเทียบ (รวมอยู่ในการทดสอบ: string, vector, deque, list, map)

                    Allocation on declare   Overhead List Node      Overhead Map Node

VC8                 map, list               8 Byte                  16 Byte
STLPort 5.2 (VC8)   deque                   8 Byte                  16 Byte
Paulhodge's EASTL   (none)                  8 Byte                  16 Byte

สตริงเอาต์พุต VC8 / เวกเตอร์ / deque / list / map:

===============================================
my_string ctor start
my_string ctor end
my_string add 3 chars
my_string add a huge number of chars chars
  my_allocator::allocate    128 byte
my_string copy
  my_allocator::allocate    128 byte
my_string copy on write test
my_string dtors start
  my_allocator::deallocate  128 byte
  my_allocator::deallocate  128 byte

===============================================
vector ctor start
vector ctor end
  my_allocator::allocate     4 byte
  my_allocator::allocate     8 byte
  my_allocator::deallocate   4 byte
  my_allocator::allocate    12 byte
  my_allocator::deallocate   8 byte
  my_allocator::allocate    16 byte
  my_allocator::deallocate  12 byte
  my_allocator::allocate    24 byte
  my_allocator::deallocate  16 byte
vector dtor starts
  my_allocator::deallocate  24 byte

===============================================
deque ctor start
deque ctor end
deque insert start
  my_allocator::allocate    32 byte
  my_allocator::allocate    16 byte
deque insert end
deque insert start
deque insert end
deque insert start
deque insert end
deque insert start
deque insert end
deque insert start
  my_allocator::allocate    16 byte
deque insert end
deque dtor starts
  my_allocator::deallocate  16 byte
  my_allocator::deallocate  16 byte
  my_allocator::deallocate  32 byte

===============================================
list ctor start
  my_allocator::allocate    12 byte
list ctor end
list insert start
  my_allocator::allocate    12 byte
list insert end
list insert start
  my_allocator::allocate    12 byte
list insert end
list insert start
  my_allocator::allocate    12 byte
list insert end
list insert start
  my_allocator::allocate    12 byte
list insert end
list insert start
  my_allocator::allocate    12 byte
list insert end
list dtor starts
  my_allocator::deallocate  12 byte
  my_allocator::deallocate  12 byte
  my_allocator::deallocate  12 byte
  my_allocator::deallocate  12 byte
  my_allocator::deallocate  12 byte
  my_allocator::deallocate  12 byte

===============================================
map ctor start
  my_allocator::allocate    24 byte
map ctor end
map insert start
  my_allocator::allocate    24 byte
map insert end
map insert start
  my_allocator::allocate    24 byte
map insert end
map insert start
  my_allocator::allocate    24 byte
map insert end
map insert start
  my_allocator::allocate    24 byte
map insert end
map insert start
  my_allocator::allocate    24 byte
map insert end
map dtor starts
  my_allocator::deallocate  24 byte
  my_allocator::deallocate  24 byte
  my_allocator::deallocate  24 byte
  my_allocator::deallocate  24 byte
  my_allocator::deallocate  24 byte
  my_allocator::deallocate  24 byte

STLPort 5.2 ผลลัพธ์ที่คอมไพล์ด้วย VC8

===============================================
my_string ctor start
my_string ctor end
my_string add 3 chars
my_string add a huge number of chars chars
  my_allocator::allocate    115 byte
my_string copy
  my_allocator::allocate    115 byte
my_string copy on write test
my_string dtors start
  my_allocator::deallocate  115 byte
  my_allocator::deallocate  115 byte

===============================================
vector ctor start
vector ctor end
  my_allocator::allocate     4 byte
  my_allocator::deallocate   0 byte
  my_allocator::allocate     8 byte
  my_allocator::deallocate   4 byte
  my_allocator::allocate    16 byte
  my_allocator::deallocate   8 byte
  my_allocator::allocate    32 byte
  my_allocator::deallocate  16 byte
vector dtor starts
  my_allocator::deallocate  32 byte

===============================================
deque ctor start
  my_allocator::allocate    32 byte
  my_allocator::allocate    128 byte
deque ctor end
deque insert start
deque insert end
deque insert start
deque insert end
deque insert start
deque insert end
deque insert start
deque insert end
deque insert start
deque insert end
deque dtor starts
  my_allocator::deallocate  128 byte
  my_allocator::deallocate  32 byte

===============================================
list ctor start
list ctor end
list insert start
  my_allocator::allocate    12 byte
list insert end
list insert start
  my_allocator::allocate    12 byte
list insert end
list insert start
  my_allocator::allocate    12 byte
list insert end
list insert start
  my_allocator::allocate    12 byte
list insert end
list insert start
  my_allocator::allocate    12 byte
list insert end
list dtor starts
  my_allocator::deallocate  12 byte
  my_allocator::deallocate  12 byte
  my_allocator::deallocate  12 byte
  my_allocator::deallocate  12 byte
  my_allocator::deallocate  12 byte

===============================================
map ctor start
map ctor end
map insert start
  my_allocator::allocate    24 byte
map insert end
map insert start
  my_allocator::allocate    24 byte
map insert end
map insert start
  my_allocator::allocate    24 byte
map insert end
map insert start
  my_allocator::allocate    24 byte
map insert end
map insert start
  my_allocator::allocate    24 byte
map insert end
map dtor starts
  my_allocator::deallocate  24 byte
  my_allocator::deallocate  24 byte
  my_allocator::deallocate  24 byte
  my_allocator::deallocate  24 byte
  my_allocator::deallocate  24 byte

ผลลัพธ์EASTLไม่มี deque

===============================================
my_string ctor start
my_string ctor end
my_string add 3 chars
  my_allocator::allocate     9 byte
my_string add a huge number of chars chars
  my_allocator::allocate    115 byte
  my_allocator::deallocate   9 byte
my_string copy
  my_allocator::allocate    115 byte
my_string copy on write test
my_string dtors start
  my_allocator::deallocate  115 byte
  my_allocator::deallocate  115 byte

===============================================
vector ctor start
vector ctor end
  my_allocator::allocate     4 byte
  my_allocator::allocate     8 byte
  my_allocator::deallocate   4 byte
  my_allocator::allocate    16 byte
  my_allocator::deallocate   8 byte
  my_allocator::allocate    32 byte
  my_allocator::deallocate  16 byte
vector dtor starts
  my_allocator::deallocate  32 byte

===============================================
list ctor start
list ctor end
list insert start
  my_allocator::allocate    12 byte
list insert end
list insert start
  my_allocator::allocate    12 byte
list insert end
list insert start
  my_allocator::allocate    12 byte
list insert end
list insert start
  my_allocator::allocate    12 byte
list insert end
list insert start
  my_allocator::allocate    12 byte
list insert end
list dtor starts
  my_allocator::deallocate  12 byte
  my_allocator::deallocate  12 byte
  my_allocator::deallocate  12 byte
  my_allocator::deallocate  12 byte
  my_allocator::deallocate  12 byte

===============================================
map ctor start
map ctor end
map insert start
  my_allocator::allocate    24 byte
map insert end
map insert start
  my_allocator::allocate    24 byte
map insert end
map insert start
  my_allocator::allocate    24 byte
map insert end
map insert start
  my_allocator::allocate    24 byte
map insert end
map insert start
  my_allocator::allocate    24 byte
map insert end
map dtor starts
  my_allocator::deallocate  24 byte
  my_allocator::deallocate  24 byte
  my_allocator::deallocate  24 byte
  my_allocator::deallocate  24 byte
  my_allocator::deallocate  24 byte

สิ่งนี้มีประโยชน์ในการรับรายละเอียดของการจัดสรรพื้นฐาน แต่น่าเสียดายที่ไม่ได้บอกเราเกี่ยวกับค่าใช้จ่ายและประสิทธิภาพแคชที่คาดหวัง

@ โจใช่มันยากที่จะตอบคำถามของคุณทั้งหมดในหนึ่งคำตอบ ฉันไม่แน่ใจว่าคุณหมายถึงอะไรกับ "ค่าใช้จ่าย" และยิ่งกว่านั้นเมื่อเทียบกับอะไร ฉันคิดว่าโดยค่าใช้จ่ายคุณหมายถึงปริมาณการใช้หน่วยความจำ
Maik Semder

โดย "ค่าใช้จ่าย" ฉันหมายถึงขนาดของอินสแตนซ์ที่ว่างเปล่าของโครงสร้างและตัววนซ้ำที่เกี่ยวข้องทั้งหมดและวิธีที่ซับซ้อนกว่าจัดการการจัดสรร - เช่น std :: list ภายในจัดสรรมากกว่าหนึ่งโหนดในแต่ละครั้งหรือฉัน จ่ายค่าการจัดสรรฐานสำหรับแต่ละโหนด ฯลฯ ?

1
คำถามไม่มาก "กรุณาทำการเปรียบเทียบนี้" เป็น "ซึ่งเป็นแหล่งข้อมูลสำหรับการเปรียบเทียบนี้" - ฉันไม่คิดว่าดังนั้นเป็นสถานที่ที่ดีในการ "รักษา" มัน บางทีคุณควรเริ่มโยนมันลงในเว็บไซต์ของ Google หรือวิกิหรือบางสิ่งบางอย่าง

1
@ Joe ตอนนี้มันอยู่ที่นี่: p ฉันไม่สนใจที่จะย้ายไปที่เว็บไซต์อื่นฉันแค่สนใจในผลลัพธ์
Maik Semder

8

std::stringไม่คัดลอกเมื่อเขียน CoW เคยเป็นการเพิ่มประสิทธิภาพ แต่ทันทีที่มีหลายเธรดเข้ามาในรูปภาพมันเกินกว่าการมองในแง่ร้าย - มันสามารถทำให้โค้ดช้าลงโดยมีปัจจัยมากมาย มันแย่มากที่มาตรฐาน C ++ 0x สั่งห้ามไม่ให้ใช้เป็นกลยุทธ์ในการปรับใช้ ไม่เพียงแค่นั้น แต่การอนุญาตของstd::stringการวนซ้ำตัวแปลงที่ไม่แน่นอนและการอ้างอิงอักขระหมายความว่า "การเขียน" สำหรับstd::stringการใช้งานเกือบทุกครั้ง

การเพิ่มประสิทธิภาพสตริงสั้น ๆ คือประมาณ 6 ตัวอักษรฉันเชื่อว่าหรือบางสิ่งบางอย่างในภูมิภาคนั้น ไม่อนุญาตให้ใช้เชือก - std::stringต้องเก็บหน่วยความจำต่อเนื่องสำหรับc_str()ฟังก์ชั่น ในทางเทคนิคคุณสามารถบำรุงรักษาทั้งสายที่ต่อเนื่องและเชือกในชั้นเรียนเดียวกัน แต่ไม่มีใครทำมัน ยิ่งไปกว่านั้นจากสิ่งที่ฉันรู้เกี่ยวกับเชือกทำให้พวกเขาปลอดภัยต่อการจัดการด้ายจะช้าอย่างไม่น่าเชื่อ - อาจจะแย่หรือแย่กว่า CoW

ไม่มีคอนเทนเนอร์ที่ทำการจัดสรรหน่วยความจำด้วยการประกาศใน STL ที่ทันสมัย คอนเทนเนอร์ที่ใช้โหนดเช่นรายการและแผนที่ที่ใช้ในการทำเช่นนี้ แต่ตอนนี้พวกเขามีการเพิ่มประสิทธิภาพสิ้นสุดที่ฝังตัวและไม่ต้องการมัน เป็นเรื่องปกติที่จะทำการเพิ่มประสิทธิภาพที่เรียกว่า "swaptimization" เมื่อคุณสลับกับคอนเทนเนอร์เปล่า พิจารณา:

std::vector<std::string> MahFunction();
int main() {
    std::vector<std::string> MahVariable;
    MahFunction().swap(MahVariable);
}

แน่นอนใน C ++ 0x นี่คือซ้ำซ้อน แต่ใน C ++ 03 แล้วเมื่อมันถูกใช้โดยทั่วไปถ้า MahVariable จัดสรรหน่วยความจำในการประกาศแล้วมันจะลดประสิทธิภาพ ฉันรู้ความจริงว่าสิ่งนี้ใช้สำหรับการจัดสรรคืนคอนเทนเนอร์ที่รวดเร็วขึ้นเช่นvectorใน MSVC9 STL ซึ่งไม่จำเป็นต้องคัดลอกองค์ประกอบ

dequeใช้บางสิ่งที่เรียกว่าเป็นรายการลิงก์ที่ไม่ได้ควบคุม โดยพื้นฐานแล้วมันเป็นรายการของอาร์เรย์ซึ่งโดยปกติจะมีขนาดคงที่ในโหนด เป็นเช่นนี้สำหรับการใช้งานส่วนใหญ่ก็ยังคงรักษาผลประโยชน์ของการเข้าถึงที่ต่อเนื่องกันทั้งข้อมูล structures- และตัดจำหน่าย O (1) การขนย้ายและความสามารถในการเพิ่มทั้งด้านหน้าและด้านหลังและvectorดีขึ้นกว่า iterator โมฆะdequeเวกเตอร์ไม่สามารถนำไปใช้งานได้เนื่องจากความซับซ้อนของอัลกอริทึมและการรับรองความถูกต้องของตัววนซ้ำ

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


"มันแย่มากที่มาตรฐาน C ++ 0x สั่งห้ามไม่ให้ใช้เป็นกลยุทธ์ในการติดตั้ง" และพวกเขาแบนเพราะการใช้งานก่อนหน้านี้ใช้มันหรือพยายามใช้มัน เห็นได้ชัดว่าคุณอาศัยอยู่ในโลกที่ทุกคนใช้ STL ที่ปรับใช้ล่าสุดอย่างเหมาะสมตลอดเวลา คำตอบนี้ไม่เป็นประโยชน์เลย

ฉันยังอยากรู้ว่าคุณสมบัติของ std :: deque คุณคิดว่าป้องกันการจัดเก็บข้อมูลที่อยู่ติดกัน - ตัววนซ้ำใช้ได้เฉพาะหลังจากการลบที่จุดเริ่มต้น / สิ้นสุดไม่ใช่กลางหรือหลังแทรกใด ๆ ซึ่งสามารถทำได้อย่างง่ายดายด้วยเวกเตอร์ และการใช้บัฟเฟอร์แบบวงกลมดูเหมือนว่าจะตอบสนองการรับประกันอัลกอริทึมทั้งหมด - O (1) ที่ถูกตัดและแทรกที่ส่วนท้าย, O (n) ลบตรงกลาง

3
@ โจ: ฉันคิดว่า CoW ได้รับการกล่าวขานว่าเป็นสิ่งที่ไม่ดีนับตั้งแต่ช่วงปลายยุค 90 มีการใช้งานสตริงที่ใช้มัน - สะดุดตา CString- แต่นั่นไม่ได้หมายความว่าstd::stringเวลานั้น คุณไม่จำเป็นต้องใช้สิ่งใหม่ล่าสุดและยิ่งใหญ่ที่สุดในการใช้งาน STL สำหรับสิ่งนั้น msdn.microsoft.com/en-us/library/22a9t119.aspxกล่าวว่า "ถ้าองค์ประกอบถูกแทรกไว้ด้านหน้าการอ้างอิงทั้งหมดจะยังคงใช้ได้" ไม่แน่ใจว่าคุณตั้งใจจะใช้สิ่งนั้นด้วยบัฟเฟอร์แบบวงกลมเนื่องจากคุณจะต้องปรับขนาดเมื่อมันเต็ม
DeadMG

gotw.ca/publications/optimizations.htm กรกฎาคม 1999
DeadMG

แน่นอนว่าฉันจะไม่ปกป้องวัวเป็นเทคนิคการใช้งาน แต่ฉันก็ไม่ได้ไร้เดียงสาว่าซอฟต์แวร์ยังคงสามารถนำไปใช้งานได้อย่างต่อเนื่องโดยใช้เทคนิคที่ไม่ดีหลังจากที่พวกเขาถูกระบุว่าเป็นคนจน ตัวอย่างเช่นการทดสอบของ Maik ด้านบนจะแสดง stdlib ที่ทันสมัยซึ่งจัดสรรให้กับการประกาศ ขอบคุณสำหรับตัวชี้เกี่ยวกับความถูกต้องอ้างอิง deque (สำหรับ nitpick เวกเตอร์สามารถตอบสนองการรับประกันทั้งหมดเกี่ยวกับการตรวจสอบความถูกต้องของตัววนซ้ำและความซับซ้อนของอัลกอริทึมนั้นข้อกำหนดนั้นไม่ใช่ทั้งสองอย่าง) หากมีสิ่งใดฉันเห็นสิ่งนี้ว่าเป็นสิ่งจำเป็นสำหรับเอกสารเพิ่มเติม

2

คำถามไม่มาก "กรุณาทำการเปรียบเทียบนี้" เป็น "ซึ่งเป็นแหล่งข้อมูลสำหรับการเปรียบเทียบนี้"

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

ไม่มีเลย

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

มีโปรแกรมเมอร์แน่นอนว่าใครสนใจเรื่องแบบนี้ แต่พวกเขาสาบานตนโดยใช้ห้องสมุดมาตรฐานเมื่อนานมาแล้ว

ดังนั้นคุณมีโปรแกรมเมอร์กลุ่มหนึ่งที่ไม่สนใจเลย และโปรแกรมเมอร์อีกกลุ่มที่สนใจถ้าใช้มันอยู่ แต่เนื่องจากไม่ได้ใช้มันก็ไม่สนใจ เนื่องจากไม่มีใครใส่ใจเกี่ยวกับมันจึงไม่มีข้อมูลที่แท้จริงเกี่ยวกับเรื่องแบบนี้ มีแพทช์ข้อมูลที่ไม่เป็นทางการที่นี่และที่นั่น (Effective C ++ มีส่วนของ std :: string implementations และความแตกต่างมากมายระหว่างพวกมัน) แต่ไม่มีอะไรครอบคลุม และแน่นอนว่าไม่มีอะไรทันสมัย


คำตอบแบบเก็งกำไร +1 อาจเป็นจริง -1 ไม่สามารถพิสูจน์ได้
ชะลอตัวลงกาเวียร์

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