來自VC++小組的VS2010 Beta 1常見問題報(bào)告
原創(chuàng)【51CTO獨(dú)家報(bào)道】Visual Studio 2010 Beta 1已經(jīng)發(fā)布了一周有余。這期間,Visual C++小組一直在測(cè)試VC++在VS 2010 Beta 1下運(yùn)行的情況(或者叫做VC10 Beta 1)。以下是VC++小組的類庫(kù)開發(fā)者Stephan T. Lavavej帶來的幾個(gè)可能導(dǎo)致原有代碼崩潰的問題報(bào)告。
Visual Studio 2010 Beta 1 is now available for download. I've recently blogged about how Visual C++ in VS 2010 Beta 1, which I refer to as VC10 Beta 1, contains compiler support for five C++0x core language features: lambdas, auto, static_assert, rvalue references, and decltype. It also contains a substantially rewritten implementation of the C++ Standard Library, supporting many C++0x standard library features. In the near future, I'll blog about them in Part 4 and beyond of "C++0x Features in VC10", but today I'm going to talk about the STL changes that have the potential to break existing code, which you'll probably want to know about before playing with the C++0x goodies.
(VS2010 Beta 1現(xiàn)在可以下載了。我最近寫了些博文,關(guān)于Visual C++在VS 2010 Beta 1版中對(duì)5個(gè)C++0x核心語(yǔ)言:lambda,auto,static_assert,rvalue references以及decltype的支持情況。我之后會(huì)用VC10 Beta 1這個(gè)詞來說明。……今天我將討論一下一些有可能會(huì)導(dǎo)致現(xiàn)有代碼崩潰的幾個(gè)STL變動(dòng)。在你使用C++0x開發(fā)之前可能會(huì)想要了解一下。)
問題1:error C3861: 'back_inserter': identifier not found
在VC9 SP1下這是沒問題的:
|
VC10 Beta 1下就有問題了:
C:\Temp﹥cl /EHsc /nologo /W4 back_inserter.cpp |
出了什么問題?
解決方法:#include ﹤iterator﹥
The problem was that back_inserter() was used without including ﹤iterator﹥. The C++ Standard Library headers include one another in unspecified ways. "Unspecified" means that the Standard allows but doesn't require any header X to include any header Y. Furthermore, implementations (like Visual C++) aren't required to document what they do, and are allowed to change what they do from version to version (or according to the phase of the moon, or anything else). That's what happened here. In VC9 SP1, including ﹤algorithm﹥ dragged in ﹤iterator﹥. In VC10 Beta 1, ﹤algorithm﹥ doesn't drag in ﹤iterator﹥.
(問題在于,back_inserter()在沒有include ﹤iterator﹥的情況下被實(shí)用。C++標(biāo)準(zhǔn)庫(kù)的headers會(huì)通過某種未定義的方式將其他headers包括進(jìn)來?!璙C9 SP1下,include﹤algorithm﹥順帶的就包括了﹤iterator﹥,但在VC10 Beta 1下需要單獨(dú)寫明。)
When you use a C++ Standard Library component, you should be careful to include its header (i.e. the header that the Standard says it's supposed to live in). This makes your code portable and immune to implementation changes like this one.
There are probably more places where headers have stopped dragging in other headers, but ﹤iterator﹥ is overwhelmingly the most popular header that people have forgotten to include.
注意:Range Insertion和Range Construction
By the way, when seq is a vector, deque, or list, instead of writing this:
(當(dāng)seq是一個(gè)vector,deque或list的時(shí)候,不要這樣寫:)
copy(first, last, back_inserter(seq)); // 這是不好的!
而應(yīng)該這樣寫:
seq.insert(seq.end(), first, last); // Range Insertion - 好的寫法
如果只是在創(chuàng)建seq,只要這樣寫就可以了:
vector﹤T﹥ seq(first, last); // Range Construction - 好的寫法
They're not only slightly less typing, they're also significantly more efficient. copy()-to-back_inserter() calls push_back() repeatedly, which can trigger multiple vector reallocations. Given forward or better iterators, range insertion and range construction can just count how many elements you've got, and allocate enough space for all of them all at once. This is also more efficient for deque, and you may as well do it for list too.
#p#
問題2: error C2664: 'std::vector﹤_Ty﹥::_Inside' : cannot convert parameter 1 from 'IUnknown **' to 'const ATL::CComPtr﹤T﹥ *'
在VC9 SP1下這是沒問題的:
C:\Temp﹥type vector_ccomptr.cpp |
VC10 Beta 1下就有問題了:
C:\Temp﹥cl /EHsc /nologo /W4 vector_ccomptr.cpp |
出了什么問題?
解決方法:使用CAdapt
The Standard containers prohibit their elements from overloading the address-of operator. CComPtr overloads the address-of operator. Therefore, vector﹤CComPtr﹤T﹥﹥ is forbidden (it triggers undefined behavior). It happened to work in VC9 SP1, but it doesn't in VC10 Beta 1. That's because vector now uses the address-of operator in push_back(), among other places.
The solution is to use ﹤atlcomcli.h﹥'s CAdapt, whose only purpose in life is to wrap address-of-overloading types for consumption by Standard containers. vector﹤CAdapt﹤CComPtr﹤T﹥﹥﹥ will compile just fine. In VC10 Beta 1, I added operator-﹥() to CAdapt, allowing v[i]-﹥Something() to compile unchanged. However, typically you'll have to make a few other changes when adding CAdapt to your program. operator.() can't be overloaded, so if you're calling CComPtr's member functions like Release(), you'll need to go through CAdapt's public data member m_T . For example, v[i].Release() needs to be transformed into v[i].m_T.Release() . Also, if you're relying on implicit conversions, CAdapt adds an extra layer, which will interfere with them. Therefore, you may need to explicitly convert things when pushing them back into the vector.
(標(biāo)準(zhǔn)容器禁止其元素將運(yùn)算符的address-of過載。CComPtr將運(yùn)算符的address-of過載,導(dǎo)致 vector﹤CComPtr﹤T﹥﹥被禁止。這是因?yàn)?,在VC9 SP1中,vector并在push_back()中使用不使用運(yùn)算符的address-of,但在VC10 Beta 1中是使用的。
解決方法就是使用﹤atlcomcli.h﹥的CAdapt?!?BR>
#p#
問題3: error C2662: 'NamedNumber::change_name' : cannot convert 'this' pointer from 'const NamedNumber' to 'NamedNumber &'
在VC9 SP1下這是沒問題的:
C:\Temp﹥type std_set.cpp |
VC10 Beta 1下就有問題了:
C:\Temp﹥cl /EHsc /nologo /W4 std_set.cpp |
出了什么問題?
解決方法:Respect set Immutability (尊重set的不變性)
The problem is modifying set/multiset elements.
(問題出在set/multiset元素的修改上。)
In C++98/03, you could get away with modifying set/multiset elements as long as you didn't change their ordering. (Actually changing their ordering is definitely crashtrocity, breaking the data structure's invariants.)
C++0x rightly decided that this was really dangerous and wrong. Instead, it flat-out says that "Keys in an associative container are immutable" (N2857 23.2.4/5) and "For [set and multiset], both iterator and const_iterator are constant iterators" (/6).
(C++0x決定,修改set/multiset元素是危險(xiǎn)的和不正確的?!?/P>
VC10 Beta 1 enforces the C++0x rules.
(VC10 Beta 1遵循C++0x的規(guī)則。)
There are many alternatives to modifying set/multiset elements.
(以下是修改set/multiset元素的一些代替的方法。)
◆You can use map/multimap, separating the immutable key and modifiable value parts.
◆You can copy, modify, erase(), and re-insert() elements. (Keep exception safety and iterator invalidation in mind.)
◆ You can use set/multiset﹤shared_ptr﹤T﹥, comparator﹥, being careful to preserve the ordering and proving once again that anything can be solved with an extra layer of indirection.
◆You can use mutable members (weird) or const_cast (evil), being careful to preserve the ordering. I strongly recommend against this.
I should probably mention, before someone else discovers it, that in VC10 Beta 1 we've got a macro called _HAS_IMMUTABLE_SETS . Defining it to 0 project-wide will prevent this C++0x rule from being enforced. However, I should also mention that _HAS_IMMUTABLE_SETS is going to be removed after Beta 1. You can use it as a temporary workaround, but not as a permanent one.
#p#
問題4:Specializing stdext::hash_compare
If you've used the non-Standard ﹤hash_set﹥ or ﹤hash_map﹥ and specialized stdext::hash_compare for your own types, this won't work anymore, because we've moved it to namespace std. ﹤hash_set﹥ and ﹤hash_map﹥ are still non-Standard, but putting them in namespace stdext wasn't accomplishing very much.
(如果你為你的type使用非標(biāo)準(zhǔn)話的 ﹤hash_set﹥或﹤hash_map﹥,以及特別的stdext::hash_compare,那你會(huì)發(fā)現(xiàn)這里沒法兒用了,因?yàn)樗鼈儽灰频搅嗣臻g下。 ……)
解決方法:使用 ﹤unordered_set﹥ 或﹤unordered_map﹥
TR1/C++0x ﹤unordered_set﹥ and ﹤unordered_map﹥ are powered by the same machinery as ﹤hash_set﹥ and ﹤hash_map﹥, but the unordered containers have a superior modern interface. In particular, providing hash and equality functors is easier.
If you still want to use ﹤hash_set﹥ and ﹤hash_map﹥, you can specialize std::hash_compare, which is where it now lives. Or you can provide your own traits class.
By the way, for those specializing TR1/C++0x components, you should be aware that they still live in std::tr1 and are dragged into std with using-declarations. Eventually (after VC10) this will change.
This isn't an exhaustive list, but these are the most common issues that we've encountered. Now that you know about them, your upgrading experience should be more pleasant.
(列表并不全面,但是這是我們所最常遇到的問題?,F(xiàn)在你也知道了,希望你的更新過程更加愉快。)
Stephan T. Lavavej
Visual C++ Libraries Developer
內(nèi)容來源:Visual C++ 小組博客
【編輯推薦】