Microsoft KB Archive/823841

= BUG: The default behavior of the for statement destroys the object incorrectly =

Article ID: 823841

Article Last Modified on 5/31/2007

-

APPLIES TO


 * Microsoft Visual C++ .NET 2002 Standard Edition

-





SYMPTOMS
When you declare an object in the init-expression element of the for loop in Microsoft Visual C++ .NET 2002, and the object is used outside the scope of the for statement, you may receive unwanted results. Note In Microsoft Visual C++ .NET 2003, you may receive the following compiler error message:

error C2065: : undeclared identifier



CAUSE
In Visual C++ .NET 2002, when the object is created in the init-expression element of the for statement, the object is destroyed as the object goes outside the scope of the for statement. This behavior occurs even though the object is accessible outside the scope of the for statement.



RESOLUTION
When you migrate an existing Visual C++ 6.0 project to Visual C++ .NET 2002, always compile the migrated project in Visual C++ .NET 2002 with the /Zc:forScope compiler option. When you use the the /Zc:forScope compiler option, you may receive a compiler error message while compiling the project. For each object that you receive a compiler error for, declare the object before the for statement. The following is the modified code: MyClass mc = 10; for(mc;--mc) { } printf(&quot;Value of mc.m_i = %d\n&quot;,mc.m_i);



STATUS
Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.



Steps to Reproduce the Behavior
 Start Visual Studio .NET 2002. On the File menu, point to New, and then click Project. Click Visual C++ Projects under Project Types, and then click Win32 Console Application under Templates.  Paste the following code in the .cpp project: class MyClass {

public: int m_i; MyClass(int i):m_i(i) {       printf(&quot;From the constructor = %d\n&quot;,m_i); }   ~MyClass {       printf(&quot;From The destructor = %d\n&quot;, m_i); }   operator bool {       return m_i != 0?true:false; }   MyClass& operator-- {       --m_i; return *this; } };

int _tmain(int argc, _TCHAR* argv[]) {   for(MyClass mc = 10;mc;--mc) {   }    printf(&quot;Value of mc.m_i = %d\n&quot;,mc.m_i); return 0; }  Press the CTRL + F5 key combination to compile and to run the project. You may receive the following output in the Console window:

From the constructor = 10

From The desctructor = 0

Value of mc.m_i = 0

</li></ol>

Notice that the object is destroyed as it goes outside the scope of the for statement.

Note According to the C++ standards (Section 6.5.3.3 of ISO:IES 14882:1998 E), the variable that is declared in the init-expression of the for statement has a scope that is limited to the scope of the for statement. Accessing the variable outside the scope of the for statement causes undefined behavior.

By default, under /Ze (Microsoft Extension for C++), a variable that is declared in a for statement remains in scope until the enclosing scope ends for the for statement.

Visual C++ 6.0 does not destroy the object because the object goes outside the scope of the for statement.

Be careful when you convert a project from Visual C++ 6.0 to Visual C++ .NET 2002. Generally, you declare and initialize Standard Template Library ( STL) iterators in the init-expression element of the for statement, and when you compile and run the converted projects in Visual C++ .NET 2002, you may receive unwanted results.

<div class="references_section">