代码之家  ›  专栏  ›  技术社区  ›  Oleg Razgulyaev

C++中的运算符优先级对于指针和迭代器是否不同?

  •  6
  • Oleg Razgulyaev  · 技术社区  · 16 年前

    下面的代码说明了这一区别:

    #include <iostream>
    #include <string>
    
    int main()
    {
            char s[] = "ABCD";
            std::string str(s);
    
            char *p = s;
            while(*p) {
                    *p++ = tolower(*p);          // <-- incr after assignment
            }
            std::cout << s << std::endl;
    
            std::string::iterator it = str.begin(), end = str.end();
            while(it != end) {
                    *it++ = tolower(*it);        // <-- incr before assignment ?
            }
            std::cout << str << std::endl;
    
            return 0;
    }
    

    它产生输出:

    abcd
    bcd
    

    如果我们分离赋值操作和增量运算符:

    while(it != end) {
      *it = tolower(*it);        // <-- incr before assignment ?
      it++;
    }
    

    输出将如预期一样。

    原始代码有什么问题?

    $ g++ --version
    g++ (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)
    Copyright (C) 2004 Free Software Foundation, Inc.
    
    3 回复  |  直到 16 年前
        1
  •  9
  •   Kirill V. Lyadvinsky    16 年前

    问题是,对 operator= 未指定。这是根据C++标准5.2.2/8。考虑以下事项:

    *it++ = tolower(*it);
    

    等于

    operator=( *it++, tolower(*it) );
    

    现在 *it++ 可以提前计算 tolower(*it) 反之亦然。

        2
  •  2
  •   Dean Harding    16 年前
    *it++ = tolower(*it); 
    *p++ = tolower(*p);
    

    这两行都调用未定义的行为。不能在单个语句中多次修改变量的值(++修改一次,运算符=修改两次)。

    所以,你得到不同的值这一事实并不令人惊讶。

        3
  •  2
  •   CB Bailey    16 年前

    对于指针和迭代器,语法的工作方式完全相同。运算符所隐含的操作将转换为类类型对象(如大多数迭代器)的函数调用。

    但是,代码的问题不在于运算符优先级,在这两行中,递增操作和第二次读取语句中其他地方递增的同一变量之间没有顺序。因此,您有未定义的行为,因此他可能看到程序中的任何行为,包括您看到的结果。

    *p++ = tolower(*p);
    
    *it++ = tolower(*it);
    

    您需要以定义序列的方式重新编写此语句。我猜你想要这样的东西。

    char c = tolower(*p);
    *p++ = c;