C++转换参数初始化问题

C++ transform parameter initialization question

本文关键字:问题 初始化 参数 转换 C++      更新时间:2023-10-16

我试图将字符串转换为小写,并使用std::transformstd::tolower将其存储在另一个变量中。我第一次尝试:

string str1("Hello");
string lowerStr1;
transform(str1.begin(), str1.end(), lowerStr1.begin(), ::tolower);
cout << lowerStr1 << endl;

但是,lowerStr1不包含任何内容。在用str1初始化lowerStr1之后,我得到了期望的结果。我想知道这背后的直觉。有人能解释一下为什么lowerStr1在这种情况下应该初始化吗?

lowerStr1为空,std::transform不会在其中插入元素。

std::transform将给定函数应用于一个范围,并将结果存储在另一个范围中,从d_first开始。

您可以使用std::back_inserter,它构造一个std::back_insert_iterator,它将在容器上调用push_back()来插入元素。

transform(str1.begin(), str1.end(), back_inserter(lowerStr1), ::tolower);

或者预先制作包含5个元素的CCD_ 14。

string lowerStr1(5, '');
transform(str1.begin(), str1.end(), lowerStr1.begin(), ::tolower);

string lowerStr1;
lowerStr1.resize(5);
transform(str1.begin(), str1.end(), lowerStr1.begin(), ::tolower);

有人能解释一下为什么lowerStr1在这种情况下应该初始化吗?

这是因为您如上所述预先初始化了包含5个元素的lowerStr1。初始化元素的值实际上并不重要。

这是因为您对std::transform的调用在逻辑上等效于以下代码:

auto b=str1.begin();
auto e=str1.end();
auto p=lowerStr1.begin();
while (b != e)
{
*p=tolower(*b);
++b;
++e;
}

但是lowerStr1是一个完全空的字符串。粗略地说,lowerStr1.begin()为您提供了一个指向空字符串的指针。因此,对该指针进行写入,雪上加霜的是,将其递增并继续对其进行写入,会导致未定义的行为、内存损坏和崩溃的可能性。

您不会通过抓取指向空字符串的指针,然后在该指针中乱写来向该字符串添加内容。有几种方法可以正确地做到这一点,使用push_back((或insert((方法。您还可以使用一个迭代器来实现这一点,比如std::back_insert_iterator,它可以与std::transform一起使用。

通用算法不会改变容器的大小。您需要使用一个迭代器适配器,它以一种特殊的方式实现operator=,以便它实际插入元素。因此,您可以使用back_inserter(lowerStr1)来确保lowerStr1trasform()执行分配时得到扩展。

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string str1("Hello");
string lowerStr1;
transform(str1.begin(), str1.end(), std::back_inserter(lowerStr1), ::tolower);
cout << lowerStr1 << endl;
}