SORU
28 HAZİRAN 2011, Salı


Neden C programcıları 'yeni kullanımını en aza indirmek gerekir'?

Taşma soru ** 29 one of the comments Yığın rastladım şöyle diyor:

Çok new durdurunuz. Yeni bir yere kullanılan herhangi bir sebep göremiyorum yaptın. C değeri nesneleri oluşturabilir ve biri dili kullanarak için büyük bir avantaj. Ayırmak zorunda değilsiniz öbek her şeyi*. Java bir programcı gibi düşünmeyi bırak.

*Sabit yalnış anlatmış "yığın" alıntı.

Ne demek istediğini gerçekten emin değilim. Neden nesneleri C değeri ile mümkün olduğunca sık oluşturulmalıdır, ve dahili olarak ne fark eder? Cevap yanlış mı anladım?

CEVAP
28 HAZİRAN 2011, Salı


İki yaygın olarak kullanılan bellek ayırma tekniği vardır: Otomatik ayırma ve dinamik ayırma. Genellikle, her biri için belleğe karşılık gelen bir bölge var: stack ve heap.

Yığın

Yığın her zaman sıralı bir şekilde bellek ayırır. Sana ters sırada belleği serbest bırakmak için bunu gerektirdiği için bunu yapmak olabilir (İlk, Son: FİLO). Bu, birçok programlama dillerinde yerel değişkenler için bellek ayırma tekniğidir. En az muhasebe gerektirdiğinden çok, çok hızlı ve ayırmak için bir sonraki Adres örtülü.

C , bu denirotomatik depolamadepolama otomatik olarak kapsam sonunda iddia etti. Geçerli kod bloğu yürütme ({} kullanarak sınırlandırılmış) tamamlanır tamamlanmaz, Bu blok içinde tüm değişkenler için bellek otomatik olarak toplanır. Bu da şu an neredeyıkıcılarkaynağa temizlemek için çağırdı.

Yığın

Öbek daha esnek bir bellek ayırma modu için izin verir. Defter tutma daha karmaşık ve ayırma yavaştır. Örtülü bırakma noktası yok çünkü, hafıza el ile delete delete[] (free C) kullanarak serbest bırakmalısınız. Ancak, örtülü bir çıkış noktası olmaması öbek esneklik anahtarıdır.

Dinamik ayırma kullanma nedenleri

Öbek kullanarak yavaş ve olası bellek sızıntısı veya bellek parçalanmasına neden olsa bile, daha az sınırlı olarak mükemmel dinamik ayırma için iyi kullanım örnekleri var.

İki önemli sebep dinamik ayırma kullanmak için:

  • Ne kadar derleme zamanında ihtiyacın olduğunu bilmiyorsun. Bir metin dizesi halinde dosyanın okurken örneğin, genellikle dosya ne kadar program bitene kadar ayırmaya karar veremezsin var, ne olduğunu bilmiyorum.

  • Geçerli blok ayrıldıktan sonra saklandığı bellek tahsis etmek istiyorum. Örneğin, bir dosyanın içeriğini gönderir 12* *bir fonksiyon yazmak isteyebilirsiniz. Yığın tüm dosya içeriğini saklamak olabilir olsa bile, bu durumda, bir işlevin dönüş ve ayrılan bellek bloğu devam edebilirsin.

Neden dinamik ayırma genellikle gereksizdir

C yapısı olarak adlandırılan düzgün bir şey varyıkıcı. Bu mekanizma, bir değişkeni yaşam ile kaynağı ömrü zamankinden kaynaklarını yönetmek için izin verir. Bu tekniği RAII denir ve C ayırt edici noktasıdır . "Sarar" içine nesneleri kaynakları. std::string mükemmel bir örnektir. Bu parçacığı:

int main ( int argc, char* argv[] )
{
    std::string program(argv[0]);
}

aslında ayırır bellek değişken bir miktar. std::string nesne ayırır bellek yığını kullanarak ve yıkıcı serbest bırakır. Bu durumda, sen yaptındeğilel ile tüm kaynakları yönetmek için lazım ve hala dinamik bellek ayırma faydaları var.

Özellikle, bu parçasında anlamına gelir:

int main ( int argc, char* argv[] )
{
    std::string * program = new std::string(argv[0]);  // Bad!
    delete program;
}

gereksiz dinamik bellek ayırma. Program daha yazmayı gerektirir (!) ve bellek ayırması için unutma riskini tanıttı. Hiçbir belirgin parası ile yapar.

Neden otomatik depolama mümkün olduğunca sık kullanmak gerekir

Temelde, son paragraf özetliyor. Mümkün olduğunca sık otomatik depolama kullanarak yapar programları:

  • yazın daha hızlı;
  • çalıştırıldığında daha hızlı;
  • /kaynak sızıntısı bellek daha az eğilimli.

Bonus puan

Başvurulan söz konusu, ek endişeler vardır. Özellikle şu sınıf:

class Line {
public:
    Line();
    ~Line();
    std::string* mString;
};

Line::Line() {
    mString = new std::string("foo_bar");
}

Line::~Line() {
    delete mString;
}

Aslında şunu bir daha kullanmak çok daha riskli

class Line {
public:
    Line();
    std::string mString;
};

Line::Line() {
    mString = "foo_bar";
    // note: there is a cleaner way to write this.
}

Nedeni std::string düzgün bir kopya kurucu tanımlar. Aşağıdaki programı deneyin:

int main ()
{
    Line l1;
    Line l2 = l1;
}

Orijinal sürümü kullanarak, bu program aynı dize üzerinde delete iki kez kullanır gibi olası kalabilir. Değiştirilmiş bir sürümünü kullanarak Line Her örnek kendi dize sahip olacakörnekkendi belleği ile , her iki program sonunda çıkacak.

Diğer notlar

RAII geniş kullanımı tüm yukarıdaki sebeplerden dolayı C En iyi yöntem olarak kabul edilir. Ancak, hemen belli olan ek bir yararı yoktur. Temel olarak, parçalarının toplamından daha iyi. Bütün mekanizmaoluşturur. Bu ölçekler.

Eğer bir yapı bloğu Line sınıf kullanıyorsanız:

 class Table
 {
      Line borders[4];
 };

Sonra

 int main ()
 {
     Table table;
 }

std::string örnekleri, dört Line örnekleri, Table örnek ve tüm dize içeriğini ve . ayırdığı dört ^em>her şey otomatik olarak yüklenecektir serbest.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Epic Tutorials for iPhone, iPad and iOS

    Epic Tutoria

    18 EYLÜL 2011
  • Eric Anthony

    Eric Anthony

    13 AĞUSTOS 2011
  • Keith Anthe

    Keith Anthe

    26 NİSAN 2011