BKJIA獨家報道】Visual Studio 2010 Beta 1已經發布了一周有余。這期間,Visual C++小組一直在測試VC++在VS 2010 Beta 1下運行的情況或者叫做VC10 Beta 1)。以下是VC++小組的類庫開發者Stephan T. Lavavej帶來的幾個可能導致原有代碼崩潰的問題報告。
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現在可以下載了。我最近寫了些博文,關於Visual C++在VS 2010 Beta 1版中對5個C++0x核心語言:lambda,auto,static_assert,rvalue references以及decltype的支持情況。我之後會用VC10 Beta 1這個詞來說明。……今天我將討論一下一些有可能會導致現有代碼崩潰的幾個STL變動。在你使用C++0x開發之前可能會想要了解一下。)
問題1:error C3861: 'back_inserter': identifier not found
在VC9 SP1下這是沒問題的:
C:\Temp﹥type back_inserter.cpp
#include ﹤algorithm﹥
#include ﹤iostream﹥
#include ﹤ostream﹥
#include ﹤vector﹥
using namespace std;
int square(const int n) {
return n * n;
}
int main() {
vector﹤int﹥ v;
v.push_back(11);
v.push_back(22);
v.push_back(33);
vector﹤int﹥ dest;
transform(v.begin(), v.end(), back_inserter(dest), square);
for (vector﹤int﹥::const_iterator i = dest.begin(); i != dest.end(); ++i) {
cout ﹤﹤ *i ﹤﹤ endl;
}
}
C:\Temp﹥cl /EHsc /nologo /W4 back_inserter.cpp
back_inserter.cpp
C:\Temp﹥back_inserter
121
484
1089
VC10 Beta 1下就有問題了:
C:\Temp﹥cl /EHsc /nologo /W4 back_inserter.cpp
back_inserter.cpp
back_inserter.cpp(19) : error C3861: 'back_inserter': identifier not found
出了什麼問題?
解決方法:#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﹥的情況下被實用。C++標准庫的headers會通過某種未定義的方式將其他headers包括進來。……VC9 SP1下,include﹤algorithm﹥順帶的就包括了﹤iterator﹥,但在VC10 Beta 1下需要單獨寫明。)
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:
當seq是一個vector,deque或list的時候,不要這樣寫:)
copy(first, last, back_inserter(seq)); // 這是不好的!
而應該這樣寫:
seq.insert(seq.end(), first, last); // Range Insertion - 好的寫法
如果只是在創建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.