Visual C++'taki Yeni Değişiklikler

Visual C++ derleyicisinin yeni bir sürümüne yükselttiğinizde, daha önce derlenmiş ve düzgün çalışan kodlarda derleme ve/veya çalışma zamanı hatalarıyla karşılaşabilirsiniz.Bu tür sorunları neden yeni sürümü değişiklikleri olarak bilinen önemli değişiklikler, ve genellikle bunlar C++ dil standart, işlev imza veya bellek nesneleri düzenini değişikliklerini gereksinim duyduğu.

Visual C++ ortamında POD (düz eski veriler) nesne düzeninin ve COM arabirimlerinin sürümler arasında bozulmayacağı garanti edilse de, diğer nesne düzeni türleri (örneğin, devralma ve şablon örneklemeyi kapsayan senaryolarda) değişikliğe tabidir.

Algılanması ve tanılanması zor çalışma zamanı hatalarından kaçınmak için, derleyicinin farklı sürümleri kullanılarak derlenmiş ikili dosyalara hiçbir zaman statik bağlantı vermemenizi öneriyoruz.Ayrıca, bir EXE veya DLL projesini yükseltirken, bağlantı verdiği kitaplıkları da yükselttiğinizden emin olun.CRT (C Çalışma Zamanı) veya STL (Standart Şablon Kitaplığı) türleri kullanıyorsanız, bunları derleyicinin farklı sürümleri kullanılarak derlenmiş ikili dosyalar (DLL'ler dahil) arasında geçirmeyin.Daha fazla bilgi için CRT Nesnelerini DLL Sınırlarından Geçirirken Olası Hatalar.

Ayrıca, COM arabirimi ya da POD projesi olmayan bir nesne için belirli bir düzeni temel alan kodları da asla yazmamanızı öneriyoruz.Bu tür bir kod yazarsanız, yükseltme sonrasında çalışmasını sağlamalısınız.Daha fazla bilgi için ABI Sınırlarında Taşınabilirlik (Modern C++).

Bu makalede geri kalanı belirli kesme değişiklikleri açıklar Visual Studio 2013'te Visual C++.

Visual C++ Derleyicisi

  • Son anahtar sözcük daha önceleri derlendiği durumlarda artık, bir çözümlenmemiş simge hatası üretmektedir:

    struct S1 {
        virtual void f() = 0;
    };
    
    struct S2 final : public S1 {
        virtual void f();
    };
    
    int main(S2 *p)
    {
        p->f();
    }
    

    Önceki sürümlerde, çağrı sanal bir çağrı olduğundan hata verilmiyordu; ancak program çalışma zamanında çöküyordu.Artık, sınıfın son olduğu bilindiğinden bir bağlayıcı hatası verilmektedir.Bu örnekte, hatayı düzeltmek için tanımı içeren obj karşı bağlayabilirsiniz S2::f.

  • Kullandığınızda ad alanları arkadaş işlevlerde, arkadaş işlev derleyici ISO C++ Standart için uygun olduğundan bir hata iletisi alır veya ona başvuran önce yeniden belirtmesi gerekir.Örneğin, bu artık derlenmemektedir:

    namespace NS {
        class C {
            void func(int);
            friend void func(C* const) {}
        };
    
        void C::func(int) { 
            NS::func(this);  // error
        }
    }
    

    Bu kodu düzeltmek için arkadaş işlevini bildirin:

    namespace NS {
        class C {
            void func(int);
            friend void func(C* const) {}
        };
    
        void func(C* const);  // conforming fix
    
        void C::func(int) { 
            NS::func(this); 
        }
    }
    
  • C++ standart izin vermez açık uzmanlığı sınıfı.Visual C++ bazı durumlarda buna izin verse de, aşağıdaki örneğe benzer durumlarda artık, derleyici ikinci işlevi birincisinin bir özelleştirmesi olarak kabul etmediği için bir hata oluşturulmaktadır.

    template <int N>
    class S { 
    public: 
        template  void f(T& val); 
        template <> void f(char val); 
    }; 
    
    template class S<1>; 
    

    Bu kodu düzeltmek için ikinci işlevi değiştirin:

    template <> void f(char& val);
    
  • Aşağıdaki örnekte yer alan iki işlev için Visual C++ artık belirsizliği gidermeye çalışmaz ve bir hata verir:

    template<typename T> void Func(T* t = nullptr); 
    template<typename T> void Func(...); 
    
    int main() { 
        Func<int>(); // error
    } 
    

    Bu kodu düzeltmek için çağrıyı netleştirin:

    template<typename T> void Func(T* t = nullptr); 
    template<typename T> void Func(...); 
    
    int main() { 
        Func<int>(nullptr); // ok
    } 
    
  • Derleyici ISO C ++ 11 ile uyumlu yapılmadan önce, aşağıdaki kod derlenmiş ve neden x türü çözümlemek için int:

    auto x = {0}; 
    
    int y = x; 
    

    Bu kodun şimdi çözümler x bir tür için std::initializer_list<int> ve atamak için çalışan bir sonraki satırında bir hataya neden x yazmak için int.(Varsayılan olarak herhangi bir dönüştürme yoktur.) Bu kodun düzeltmek için int değiştirmek için auto:

    int x = {0}; 
    
    int y = x; 
    
  • Sağdaki değerin türü, başlatılmakta olan soldaki değerin türüyle eşleşmediğinde toplu başlatmaya artık izin verilmemektedir ve ISO C++11 Standardı tek düzen başlatmanın daraltma dönüşümleri olmadan çalışmasını gerektirdiğinden bir hata verilir.Daha önce bir daraltma dönüşümü mevcut olduğunda, hata yerine C4242 uyarısı verilmekteydi.

    int i = 0;
    char c = {i}; // error
    

    Bu kodu düzeltmek için açık bir daraltma dönüşümü ekleyin:

    int i = 0;
    char c = {static_cast<char>(i)};
    
  • Aşağıdaki başlatmaya artık izin verilmemektedir:

    void *p = {{0}};
    

    Bu kodu düzeltmek için şu formlardan birini kullanın:

    void *p = 0; 
    // or 
    void *p = {0};
    
  • Ad arama değişti. Aşağıdaki kod içinde farklı çözülene Visual Studio 2012'de Visual C++ ve Visual Studio 2013'te Visual C++:

    enum class E1 {a};
    enum class E2 {b};
    
    int main()
    {
        typedef E2 E1;
        E1::b;
    }
    

    İçindeki Visual Studio 2012'de Visual C++, E1 ifadesinde E1::b Çözümlendi ::E1 Genel kapsamdaki.İçindeki Visual Studio 2013'te Visual C++, E1 ifadesinde E1::b çözülen typedef E2 tanımında main() ve türüne sahip ::E2.

  • Nesne düzenini değişti. x64 üzerinde, bir sınıfın nesne düzeni önceki sürümlere göre değişebilmektedir.Bir sanal işlevi varsa, ancak sanal işleve sahip bir taban sınıfı yoksa, derleyicinin nesne modeli veri üyesi düzeninden sonra sanal işlev tablosuna bir işaretçi ekler.Başka bir deyişle, ilgili düzen her durumda en uygun düzen olmayabilir.Önceki sürümlerinde bir en iyi hale getirme x 64 için düzeni artırmak isteriz, ancak karmaşık kod durumlarda düzgün çalışması başarısız olduğundan, kaldırıldı Visual Studio 2013'te Visual C++.Örneğin, aşağıdaki kodu düşünün:

    __declspec(align(16)) struct S1 {
    };
    
    struct S2 {
        virtual ~S2();
        void *p;
        S1 s;
    };
    

    İçindeki Visual Studio 2013'te Visual C++, sonucunu sizeof(S2) x 64 48 olsa da, isteğe bağlı olarak önceki sürümlerinde 32 olarak değerlendirir.Bu 32 değerlendirmek için Visual Studio 2013'te Visual C++ x 64 için sanal bir işlev boş bir temel sınıf Ekle:

    __declspec(align(16)) struct S1 {
    };
    
    struct dummy { 
        virtual ~dummy() {} 
    };
    struct S2 : public dummy {
        virtual ~S2();
        void *p;
        S1 s;
    };
    

    Önceki bir sürüm en iyi duruma getirme denediğiniz kodunuzda yerler bulmak için bir derleyici bu sürümü ile birlikte kullanın /W3 derleyici seçeneği ve uyarı 4370 etkinleştirin.Örneğin:

    #pragma warning(default:4370)
    
    __declspec(align(16)) struct S1 {
    };
    
    struct S2 {
        virtual ~S2();
        void *p;
        S1 s;
    };
    

    Visual C++ derleyiciler önce üzerinde Visual Studio 2013'te Visual C++, bu iletiyi bu kodu çıkarır:

    warning C4370: 'S2' : layout of class has changed from a previous version of the compiler due to better packing
    

    x86 derleyicisi, tüm Visual C++ sürümlerinde aynı optimum altında düzen sorununu barındırır.Örneğin, bu kod x86 için derlenirse:

    struct S {
        virtual ~S();
        int i;
        double d;
    };
    

    Sonucu sizeof(S) 24'tür.Bununla birlikte, az önce x64 için sözü edilen geçici çözümü kullanırsanız bu sonuç 16'ya indirilebilir:

    struct dummy { 
        virtual ~dummy() {} 
    };
    
    struct S : public dummy {
        virtual ~S();
        int i;
        double d;
    };
    

Visual C++ Kitaplıkları

Standart Şablon Kitaplığı

Yeni iyileştirmeleri ve hata ayıklama denetimlerini etkinleştirmek için, C++ Standart Kitaplığı'nın Visual Studio uygulaması bir sürümden sonraki bir sürüme ikili uyumluluğu kasıtlı olarak bozar.Bu nedenle, C++ Standart Kitaplığı kullanıldığında, farklı sürümlerin kullanımıyla derlenmiş nesne dosyaları ve statik kitaplıklar tek bir ikili dosya (EXE veya DLL) halinde karma yapılabilir ve C++ Standart Kitaplığı nesneleri, farklı sürümler kullanılarak derlenmiş ikili dosyalar arasında geçirilemez.Bu tür karmalar, _MSC_VER uyuşmazlıklarıyla ilgili bağlayıcı hataları verir.(_MSC_VER olan derleyici'nin ana sürüm içeren makro — Örneğin, Visual Studio 2013'teki Visual C++ için 1800.) Bu onay DLL karıştırma algılayamıyor ve Visual C++ 2008 veya önceki bir sürümünü içeren bir arada algılanamadı.

Visual Studio 2013'te Visual C++, Visual C++ 2010 içinde gerçekleştirilmiş _ITERATOR_DEBUG_LEVEL uyuşmazlıklarını ve RuntimeLibrary uyuşmazlıklarını algılar.Bunlar meydana olduğunda derleyici seçenekleri /MT (statik sürüm), /MTd (statik hata ayıklama), /MD (dinamik sürüm), ve /MDd (dinamik hata ayıklama) karıştırılır.Daha fazla bilgi için kesme değişiklikleri Visual C++ 2012'de.

  • Kodunuz, önceki sürümün benzetilmiş diğer ad şablonlarını kabul ederse, bunu değiştirmeniz gerekir.Örneğin, yerine, allocator_traits<A>::rebind_alloc<U>::other, söylediğiniz mı allocator_traits<A>::rebind_alloc<U>.Olsa da ratio_add<R1, R2>::type gerekirse ve şimdi söylediğiniz öneri olmayan ratio_add<R1, R2>, eski yine de olduğundan derleme yapılamayacak ratio<N, D> bir "tür" typedef aynı tür zaten azaltıldığında olacağı azaltılmış oranı için gereklidir.

  • Kullanmalısınız #include <algorithm> çağırdığınızda std::min() veya std::max().

  • Mevcut kodunuz önceki sürümün benzetilmiş kapsamlı numaralandırmalarını kullanıyorsa (ad alanlarına sarmalanmış geleneksel kapsam dışı numaralandırmalar), bunu değiştirmeniz gerekir.Örneğin, türüne başvurulan std::future_status::future_status, söylediğiniz mı std::future_status.Ancak, çoğu kod etkilenmez — Örneğin, std::future_status::ready yine de derler.

  • explicit operator bool() daha katı olan operator unspecified-bool-type().explicit operator bool() Açık dönüştürmeler verir bool— Örneğin, verilen shared_ptr<X> sp, her iki static_cast<bool>(sp) ve bool b(sp) Geçerli — ve Boolean sınanabilir "bağlamsal dönüştürmeler" bool— Örneğin, if (sp), !sp, sp && whatever.Ancak, explicit operator bool() için örtük dönüştürmeler engelliyor bool, bu nedenle söylediğiniz olamaz bool b = sp; ve belirtilen bir bool dönüş türü, söylediğiniz olamaz return sp.

  • Artık gerçek değişen sayıda bağımsız değişken içeren şablonlar uygulandığına göre, _VARIADIC_MAX ve ilgili makroların bir etkisi olmaz. Halen _VARIADIC_MAX öğesini tanımlıyorsanız, sadece yok sayılır. Benzetilmiş değişen sayıda bağımsız değişken içeren şablonları farklı bir şekilde desteklemeye yönelik makro makinemizi kabul ettiyseniz, kodunuzu değiştirmeniz gerekir.

  • Sıradan anahtar sözcüklere ek olarak, STL üst bilgileri artık, içeriğe duyarlı "geçersiz kıl" ve "son" anahtar sözcüklerinden makro oluşturulmasını engellemektedir.

  • reference_wrapper/ref()/cref() Şimdi geçici nesneler için bağlamayı yasaklamaz.

  • <random> Şimdi, derleme zamanı önkoşulları katı bir biçimde zorlar.

  • Çeşitli STL türü nitelikleri "T tam bir tür olacaktır" önkoşuluna sahiptir.Derleyici artık bunu daha katı şekilde zorladığı halde, her durumda zorla kabul ettiremeyebilir.(STL önkoşulu ihlalleri tanımlanmamış davranışı tetiklediğinden, Standart, zorlamayı garanti etmez.)

  • STL desteklemediği /clr:oldSyntax.

  • C ++ 11 belirtimi içincommon_type <> sahipse beklenmeyen ve istenmeyen sonuçlarıyla; özellikle, bu sayede common_type<int, int>::type dönüş int&&.Bu nedenle, Visual C++ uygulayan kitaplık çalışma grubu sorun 2141 için önerilen çözüm, hangi yapar common_type<int, int>::type dönüş int.

    Bir yan-etkisi, bu değişikliği, kimlik durum artık çalışır (common_type<T> her zaman türünde oluşmaz T).Bu Önerilen Çözünürlük ile uyumludur, ancak önceki çalışma biçimine dayalı kodları keser.

    Bir kimlik türü ayırdedici nitelik gerektiriyorsa, standart kullanmıyorum std::identity içinde tanımlanan <type_traits> olduğundan < için geçersiz kılma > çalışmaz.Bunun yerine, gereksinimlerinize uyan kendi kimlik türü ayırt edici niteliğini uygulayın.Örnek buradadır:

    template <typename T> struct Identity {
        typedef T type;
    };
    

MFC ve ATL

  • Unicode çok popüler olduğundan ve MBCS kullanımı önemli ölçüde azaldığından MFC MBCS Kitaplığı artık Visual Studio içinde yer almamaktadır.Yeni denetimlerin ve iletilerin çoğu salt Unicode olduğundan, bu değişiklik aynı zamanda MFC'yi Windows SDK ile daha paralel halde tutar.MFC MBCS kitaplık kullanmaya devam ederseniz, ancak buradan karşıdan yükleyebileceğiniz MSDN İndirme Merkezi.Visual C++ Yeniden Dağıtılabilir Paketi'nde bu kitaplık halen yer almaktadır.

  • MFC Şerit için erişilebilirlik değiştirilir.  Bir düzey mimari yerine, şimdi hiyerarşik bir mimarisi yok. Eski davranışı çağırarak kullanmaya devam edebilirsiniz CRibbonBar::EnableSingleLevelAccessibilityMode().

  • CDatabase::GetConnect yöntemi kaldırılır. Güvenlik geliştirmek için bağlantı dizesi şimdi depolanan şifrelenmiş ve gerektiğinde; yalnızca şifresi düz metin olarak döndürülemiyor.  Dize kullanılarak alınabilir CDatabase::Dump yöntemi.

  • CWnd::OnPowerBroadcast imzası değiştirilir. Bu ileti işleyicisinin imzası ikinci parametre olarak bir LPARAM alacak şekilde değiştirilir.

  • İleti işleyicileri uygun hale getirmek için imza değiştirildi. Aşağıdaki işlevlerin parametre listeleri yeni eklenen ON_WM_* ileti işleyicilerini kullanacak şekilde değiştirilmiştir:

    • CWnd::OnDisplayChange Dönüştürülen (UINT, int, int) yerine (WPARAM, LPARAM) böylece yeni ON_WM_DISPLAYCHANGE makro ileti eşleme içinde kullanılabilir.

    • CFrameWnd::OnDDEInitiate Dönüştürülen (CWnd*, UINT, UNIT) yerine (WPARAM, LPARAM) böylece yeni ON_WM_DDE_INITIATE makro ileti eşleme içinde kullanılabilir.

    • CFrameWnd::OnDDEExecute Dönüştürülen (CWnd*, HANDLE) yerine (WPARAM, LPARAM) böylece yeni ON_WM_DDE_EXECUTE makro ileti eşleme içinde kullanılabilir.

    • CFrameWnd::OnDDETerminate Dönüştürülen (CWnd*) yerine parametre olarak (WPARAM, LPARAM) böylece yeni ON_WM_DDE_TERMINATE makro ileti eşleme içinde kullanılabilir.

    • CMFCMaskedEdit::OnCut Hiçbir parametre yerine değiştirildi (WPARAM, LPARAM) böylece yeni ON_WM_CUT makro ileti eşleme içinde kullanılabilir.

    • CMFCMaskedEdit::OnClear Hiçbir parametre yerine değiştirildi (WPARAM, LPARAM) böylece yeni ON_WM_CLEAR makro ileti eşleme içinde kullanılabilir.

    • CMFCMaskedEdit::OnPaste Hiçbir parametre yerine değiştirildi (WPARAM, LPARAM) böylece yeni ON_WM_PASTE makro ileti eşleme içinde kullanılabilir.

  • #ifdefMFC üstbilgi dosyaları s kaldırılır. Çok sayıda #ifdefMFC üstbilgisinde s ilgili desteklenmeyen Windows sürümleri dosyaları (WINVER < 0x0501) kaldırılır.

  • ATL DLL (atl120.dll) kaldırılır. ATL artık, üst bilgiler ve statik kitaplık (atls.lib) olarak sağlanmaktadır.

  • Atlsd.lib, atlsn.lib ve atlsnd.lib kaldırılır. Atls.lib artık, karakter kümesi bağımlılıkları veya hata ayıklamaya/yayınlamaya özgü kod içermez.Unicode/ANSI ve hata ayıklama/yayınlama için aynı çalıştığından, kitaplığın yalnızca tek bir sürümü gereklidir.

  • ATL/MFC İzleme aracı kaldırıldı. Bu araç, ATL DLL ile birlikte kaldırıldı ve izleme mekanizması basitleşti.CTraceCategory Oluşturucu şimdi bir parametre (kategori adı) alır ve TRACE makro işlevleri raporlama CRT hata ayıklama çağırın.

Ayrıca bkz.

Diğer Kaynaklar

Visual Studio 2013'de Visual C++ kullanmaya başlarken