一个 std::string 得到一个完全出乎意料的值

A std::string gets a totally unexpected value

本文关键字:一个 出乎意料 string std      更新时间:2023-10-16

我的类有一个成员std::string received;,在其构造函数中以空字符串初始化,以及一个将字符串打印到cout的函数printReceived

main()中,创建上述类的实例,并调用printReceived

我没有得到一个空字符串,而是得到完全出乎意料的值(但总是相同的(:

  • 如果printReceivedstd::cout<<"Received ":<<received<<std::endl;,我得到

    Received: eived: 作为输出。

  • 一个字符串常量,存在于另一个类的函数中,如果此文件已链接,则未调用该类。

这从何而来?这让我很生气...所有变量都已正确初始化。我以前从未遇到过这个问题,而且我在C++中编程了很多。

这是一个完整的最小示例:

蜂窝测试.cpp

#include "A.h"
#include <iostream>
int main()
{
    A s;
    s.println("AT+CSQ");
    
    return 0;
}

答.cpp

#include "A.h"
A::A()
: received("")
{
}
void A::println(char* s)
{
    received+=s+'n';
    treatReceived();
}
void A::treatReceived()
{
    std::cout<<"Received: "<<received<<std::endl;
}

#include <iostream>
#include <string>
class A
{
    public:
        A();
        void println(char* s);
    private:
        std::string received;
        void treatReceived();
};

生成文件

CellularTest: CellularTest.o CellularTest.cpp A.o
    g++ CellularTest.o A.o -o CellularTest
CellularTest.o: CellularTest.cpp
A.o: A.cpp A.h
clean:
    rm *.o
    rm CellularTest

我得到的输出是:

Received: eived: 

operator+= 的优先级低于 operator+ 。所以在println中,你正在这样做:

received+=(s+'n');

这就像

received+=(s+10);

这是将指针s增加 10 个字节,然后将生成的char*指向的字符串附加到 received 中,并且字符串文字Recieved:恰好存储在字符串文字AT+CSQ之后。所以内存可能看起来像AT+CSQReceived: AT+CSQ增加 10 实际上是Received: e。所以你有它。

将其更改为

received+=s;
received+='n';

或者或者

received = received + s + 'n';
void A::println(char* s)
{
    received+=s+'n';

你显然从未处理过原始字符串。首先 - 始终被视为const char*std::string - 因为修改内容是未定义的行为。其次,您的+实际上是在执行指针算术,即received += &s['n'];而不是串联。主机字符串显然不足以达到 13 左右的 IIRC n值,因此您的程序表现出未定义的行为。

如果你想在C++中使用字符串,并且你不太确定自己在做什么,请始终处理std::string,因为这种事情不可能发生。