C ++评估顺序

时间:2016-11-27 09:04:24

标签: c++ c++11 g++ clang++

我正在试图弄清楚C ++ 11规范中是否有任何内容。以下代码(GitHub link here)的预期行为:

#include <iostream>
#include <fstream>
#include <windows.h>
#include <string>
#include <vector>
#include <stdio.h>
#include <tchar.h>
#include <algorithm>
#include <string>

using namespace std;

bool caseInsensitiveStringCompare( const std::string& str1, const std::string& str2 );

int main(int argc, char* argv[]) {

    const string path = "E:\\util\\bin\\";
    const string procName = "procReal.exe";
    const string argToFilter = "-t";


    string origValue;
    string passedValue;

    for(int i = 1; i < argc; i++)
    {
        origValue.append(" ").append(argv[i]);
    }

    for(int i = 1; i < argc; i++)
    {
        if (!caseInsensitiveStringCompare(argv[i],argToFilter))
        {
            passedValue.append(" ").append(argv[i]);
        }
        else
        {
            i++; // skip over argument and it's value
        }

    }

    const LPCTSTR exeModule = (path+procName).c_str();

    std::vector<char> chars(passedValue.c_str(), passedValue.c_str() + passedValue.size() + 1u);
    LPTSTR exeArgs = &chars[0];


    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );

    GetStartupInfo(&si);

    FILE* traceFile;
  traceFile = fopen ((path+"lastRun.txt").c_str(), "w");  // This causes exeModule to change value for unknown reasons???
  fprintf(traceFile, "orig: %s%s\n", exeModule, origValue.c_str());
  fprintf(traceFile, "%s%s\n", exeModule, exeArgs);

  SetLastError(0);

    // Start the child process.
    if( !CreateProcess( exeModule,   // use module name with args for exeArgs
        exeArgs,        // Command line
        NULL,           // Process handle not inheritable
        NULL,           // Thread handle not inheritable
        TRUE,          // Set handle inheritance to FALSE
        0,              // No creation flags
        NULL,           // Use parent's environment block
        NULL, // use parent's starting directory
        &si,            // Pointer to STARTUPINFO structure
        &pi )           // Pointer to PROCESS_INFORMATION structure
    )
    {
        FILE* myfile;
        myfile = fopen ((path+"error.txt").c_str(), "w");
        fprintf(myfile, "CreateProcess failed (%d).\n", int(GetLastError()));
        fclose(myfile);
    }

    // Wait until child process exits.
    WaitForSingleObject( pi.hProcess, INFINITE );

    DWORD exit_code;
    GetExitCodeProcess(pi.hProcess, &exit_code);

    fprintf(traceFile, "Exit Code: %d\n", int(exit_code));
    fclose(traceFile);

    // Close process and thread handles.
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );

    return exit_code;
}

bool caseInsensitiveStringCompare( const std::string& str1, const std::string& str2 ) {
    std::string str1Cpy( str1 );
    std::string str2Cpy( str2 );
    std::transform( str1Cpy.begin(), str1Cpy.end(), str1Cpy.begin(), ::tolower );
    std::transform( str2Cpy.begin(), str2Cpy.end(), str2Cpy.begin(), ::tolower );
    return ( str1Cpy == str2Cpy );
}

这主要是因为发现这在struct Scalar { int data; Scalar(int x) : data(x) {} int get() { return data; } Scalar &square() { scale(data); return *this; } void scale(int rhs) { data *= rhs; } }; int main() { Scalar v(3); v.square().scale(v.get()); return v.data; } g++之间做了不同的事情:

clang++

答案似乎应该出现在n3242的§5.2.2和§5.2.5中,但我无法追踪具体内容。

1 个答案:

答案 0 :(得分:8)

如果我正确阅读了内容,则代码的行为未指定。 N3337 for C ++ 11引用:

  

§1.9[intro.execution] / 15

     

除非另有说明,否则评估各个运营商的操作数   并且个别表达的子表达式没有被排序。 [...]   如果对标量对象的副作用相对于其中任何一个都没有排序   对同一标量对象或值计算的另一个副作用   使用相同标量对象的值,行为未定义。

但随后是

  

调用函数中的每个评估(包括其他函数   在之前或之后没有特别排序的调用)   被调用函数体的执行是不确定的   关于被叫的执行顺序排序   功能 9

     

9)换句话说,函数执行不会与每个函数交错   其他

  

§5.2.2[expr.call] / 8

     

[注意:后缀表达式和。的评估   参数表达式相对于彼此都是无序的。所有   参数表达式评估的副作用在之前排序   输入功能(见1.9)。 -end note ]

因此,您对Scalar::data的修改和无关读取是不确定的。

话虽如此,它可能会在C ++ 1z中改变并定义明确:

  

N4606§5.2.2[expr.call] / 5

     

postfix-expression 在每个表达式之前排序   表达式列表和任何默认参数。一个初始化   参数,包括每个相关的值计算和边   效果,相对于任何其他的不确定地排序   参数。

因此,在C ++ 1z中,v.data应该等于81(如果我正确读取了内容)