`=`赋值给新的std::string到底赋值了什么?

What exactly is assigned by the `=` assigment to the new std::string?

我想写一个方法,应该 trim 一个 std::string 的持续和尾随白色 spaces。例如,如果方法得到“HELLO WORLD”,它应该return“HELLO WORLD”。请注意,return 字符串之间是一个白色的 space,这很重要。

这是我方法的签名:

std::string MyHandler::Trim(const std::string& toTrim)

我的方法是将 'toTrim' 参数复制到一个非常量副本中。

std::string toTrimCopy = toTrim; 

现在我想得到一个非常量迭代器并在 for 循环中从头到尾擦除任何白色space,而迭代器值是白色 space.

for (std::string::iterator it = toTrim.begin(); *it == ' '; it++)
{
    toTrimCopy.erase(it);
}

for (std::string::iterator it = toTrim.end();
     *it == ' ';
     it--)
{
    toTrimCopy.erase(it);
}

这导致编译器错误:

StringHandling.C:60:49: error: conversion from ‘std::basic_string<char>::const_iterator {aka __gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >}’ to non-scalar type ‘std::basic_string<char>::iterator {aka __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >}’ requested

我来自Java,我现在学习 C++ 3 周了。所以不要评判我。我怀疑 = 赋值将常量 char 指针分配给我的新字符串,因此我的副本隐含了一个常量值。不过我也不是很清楚。

顺便说一句,这种方法也会抛出异常:

    std::string toTrimCopy = "";
    std::strcpy(toTrimCopy, toTrim);

他说,他无法将字符串转换为字符指针。

将迭代器从 toTrim 传递给 toTrimCopy 的方法是未定义的行为,所以你很幸运,类型不匹配捕获了它。

std::string::begin 有两个重载:

 std::string::iterator std::string::begin();
 std::string::const_iterator std::string::begin() const;

字符串的constness参与重载决议。您不能从 const_iterator 初始化 iterator,因为这将允许您通过该迭代器修改基础对象。

我会把你的功能改成

namespace MyHandlerNS { // optional, could be in global namespace
    std::string Trim(std::string toTrim) {
        for (auto it = toTrim.begin(); it != toTrim.end() && *it == ' ';) {
            it = toTrim.erase(it);
        }

        for (auto it = toTrim.rbegin(); it != toTrim.rend() && *it == ' ';) {
            it = toTrim.erase(it.base());
        }

        return toTrim;
    }
}

或者使用标准算法完全摆脱循环

#include <algorithm>

namespace MyHandlerNS { // optional, could be in global namespace
    std::string Trim(std::string toTrim) {
        auto isSpace = [](char c){ return c == ' '; };

        auto it = std::find_if_not(toTrim.begin(), toTrim.end(), isSpace);
        toTrim.erase(toTrim.begin(), it);

        it = std::find_if_not(toTrim.rbegin(), toTrim.rend(), isSpace).base();
        toTrim.erase(it, toTrim.end());

        return toTrim;
    }
}

我终于决定使用正则表达式了:

std::string StringHandling::Trim (const std::string& toTrim)
{
    return std::regex_replace(toTrim, std::regex("^ +| +$"), "");
}

线程可以在这里关闭。