C++请不要问我string s=”a”+”b”分配了几次内存

本文详细解析了在C++中使用字符串进行连接操作时涉及的内存分配次数,并通过实例对比了不同情况下的内存分配差异。

C++请不要问我string s=”a”+”b”分配了几次内存

       首先我要告诉你,string s="a"+"b";在C++中连编译都通过不了,错误提示:“+:不能添加两个指针”。你说他分配几次内存。为什么报错呢,原因很简单,”a”是一个字符数组,字符数组没有自己的加法运算符。你硬是要这么写,自己实现去,当然在java,js,C#(我还是个C#程序员啊,什么时候才能成为C++程序员呢?哥带着这个难题一直在学习C++)中这句话是正确的。那是因为这些语言把一些基础的东西都封装了,或者说这些语言实现了字符数组的加法运算符。

        当我们把这句话改成string a=”a”;string s=a+”b”;就没有问题了。现在a是一个字符串,有现成的加法运算符,加法运算符的右边参数应该为字符串,字符数组,字符,指向字符串的指针等,右边参数为int,bool型的没有重载。

        那么这两句话到底分配了几次内存呢,有人说2次,有人说3次。我说4次。

        有人说编译器优化,只需要1次,编译器优化我真的管不了。

        说2次的人可能认为:“a”一次,”b”一次,共两次

        说3次的人可能认为:“a”一次,”b”一次,”a”+”b”要分配一块新的内存。因为必须重新分配一块内存,来存储”ab”。如果是a+=b;就不用了,编译器会把a+b的值存在a所在的空间中,如果空间不够,应该会分配一块更大的内存来存储a+b的值(存不下,不给一块更大的空间,行吗?)。

        以上三次是必须,第四次分配内存发生在将a+b的值赋给s,即s=”ab”。我是在反复看Effective C++时不经意间发现的。Effective C++中条款15: 让operator=返回*this的引用,解释得非常清楚。我在这里简要说一下。

       string类的operator=的源码大致如下:

 string& string::operator=(const string& rhs)
 {

   ...

   return *this;    // 返回左边的对象

   }

  因为赋值语句的右边参数不是正确的类型——它是一个字符数组”ab”,不是一个string——编译器就要产生一个临时的string对象使得函数继续运行。就是说,编译器必须产生大致像下面这样的代码:

 const string temp("ab");// 产生临时string,这句话不分配内存才怪,哈哈…
 s = temp;           // 临时string传给operator=

       如果string类的operator=的源码大致如下:(即参数中的const去掉)

 string& string::operator=( string& rhs)

   {

        ...

        return *this;    // 返回当前的对象

    }

  那么string s=a+”b”;编译肯定是通过不了的。因为”b”是个常量字符串,把常量字符串赋给non-const字符串肯定是不行的。

调用string& string::operator=方法时,参数为值传递或者是常量引用传递,都会产生临时变量,并用形参初始化临时变量,当然必须为这个临时变量分配内存,等函数调用完成,系统自动释放临时变量的内存,当然我们也知道这个临时变量的内存不是分配在堆中,而是分配在栈中。

       是的,string s=”a”+”b”;就是分配了4次内存。  

    作者:陈太汉

### C++ 中通过运算符重载实现字符串连接 在 C++ 编程语言中,可以通过 **运算符重载** 来定义 `+` 运算符的行为,从而允许两个对象(例如自定义的字符串类实例)相加并返回一个新的组合对象。这种技术可以用于模拟标准库中的 `std::string` 类型的功能。 下面是一个简单的例子,展示如何创建一个支持字符串连接操作的类: #### 自定义字符串类及其运算符重载 ```cpp #include <iostream> #include <cstring> class MyString { private: char* str; public: // 构造函数 MyString(const char* s = "") { if (s) { str = new char[strlen(s) + 1]; strcpy(str, s); } else { str = nullptr; } } // 拷贝构造函数 MyString(const MyString& other) { str = new char[strlen(other.str) + 1]; strcpy(str, other.str); } // 赋值运算符重载 MyString& operator=(const MyString& other) { if (this != &other) { delete[] str; str = new char[strlen(other.str) + 1]; strcpy(str, other.str); } return *this; } // 加法运算符重载 MyString operator+(const MyString& other) const { size_t length = strlen(str) + strlen(other.str); char* resultStr = new char[length + 1]; strcpy(resultStr, str); strcat(resultStr, other.str); MyString temp(resultStr); // 创建临时对象存储结果 delete[] resultStr; // 删除动态分配的空间 return temp; } // 输出流运算符重载 friend std::ostream& operator<<(std::ostream& os, const MyString& obj) { os << obj.str; return os; } // 析构函数 ~MyString() { delete[] str; } }; ``` 在这个示例中,我们定义了一个名为 `MyString` 的类,并实现了以下功能: - 使用指针成员变量 `char* str` 存储字符数组。 - 提供了默认构造函数、拷贝构造函数以及赋值运算符重载以管理内存资源[^5]。 - 实现了 `operator+` 方法,使得两个 `MyString` 对象能够通过 `+` 符号进行拼接[^1]。 - 定义了友元函数 `operator<<`,以便可以直接将 `MyString` 对象打印到控制台。 #### 测试代码 以下是测试上述类的一个简单程序片段: ```cpp int main() { MyString str1("Hello "); MyString str2("World"); MyString str3 = str1 + str2; // 使用重载后的 "+" 运算符 std::cout << "Concatenated Strin
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值