关于 The c++ programming language 其中的一条忠告

10.4.10 临时对象
临时对象最经常是作为算术表达式的结果出现的。例如,在求值想×*y+z过程中的某一点,部分结果x*y必须存在于某个地方。除了与性能有关的问题之外,临时对象很少成为程序员关心的问题。但这种情况确实也有可能出现。
除非一个临时对象被约束在某一个引用,或者被用于做命名对象的初始化,否则它将总在建立它的那个完整表达式结束时销毁。所谓完整表达式就是那种不是其他表达式的子表达式的表达式。
例如上述的 x*y+z为完整表达式,而x*y不是完整表达式,因为它是x*y+z的子表达式。
在c++中,标准string类里有一个成员函数从c_str(),它返回的是一个c风格的以0结尾的字符数组。此外+在这里定位以字符串的拼接。这些都是对string很有用的功能。但是,他们的组合却可能到时很隐晦的问题。例如:

    void f(stirng &s1,string &s2,string &s3)
    {
        const char *cs = (s1+s2).c_str();
        cout<<cs;
        if(strlen(cs=(s2+s3).c_str()) <8 && cs[0] == 'a')
        {
            //这里使用cs
        }
    }

你的第一反应可能是“千万不要这样写”,我也同意。然而,这种代码还是被一些人写出来了,因此值得去理解对于它的解释。
为了保存s1+s2将会产生一个临时变量,随之从这个对象里提出一个指向c风格字符串的指针。再往后——在表达式结束的时候——这个临时对象将被删除。那么由c_str()返回的那个c风格字符串在什么地方呢?或许它是作为保存s1+s2的临时对象的一部分,而在这个心事对象被销毁后,根本无法保证这个存储还存在,这样cs就会指向已经释放掉的存储,输出操作”cout”可能像所希望的那样工作,但那只能是侥幸。编译器有可能检查出这个问题的许多变形,并给出警告。
与if语句有关的列子琢磨起来更困难一点。条件将如预期的那样工作,因为建立起保存s2+s3的临时对象的完整表达式就是整个条件。但是,在进入受控语句之前,这个临时变量已经被销毁了,在那里,任何对cs的使用都不能保证工作的正确。
如何保证正确是工作:

    void f(stirng &s1,string &s2,string &s3)
    {

        cout<<s1+s2;
        string s1 = s2+s3
        if(s1.length()<8 && cs[0] == 'a')
        {
            //这里可以使用cs
        }
    }

猜你喜欢

转载自blog.csdn.net/yaowangii/article/details/80769768