【问题标题】:Reference as a parameter作为参数引用
【发布时间】:2019-03-27 10:59:17
【问题描述】:

您好,我正在尝试更改作为参考传递的 vec 的内容,我对这个概念很陌生,看不出我的代码有什么问题:

std::string pluralize(std::string const& word) {
if (uncountables.count(word) > 0) {
    return word;
}

for (auto const& r : rules) {
    if (r.matches(word)) {
        return r.pluralize(word);
    }
}

// The last rule is fully generic "append s" rule, so we cannot
// get here unless something is seriously wrong.
throw std::runtime_error("Word '" + word + "' did not match any rule");
}

std::vector<std::string> pluralize(std::vector<std::string> const& words) {

for (auto word : words) {
    word = pluralize(word);
    std::cout << word << " word from pluralize called with vec" << std::endl;
}
std::cout << words[0] << " 0 word from pluralize called with vec" << std::endl;
std::cout << words[1] << " 1 word from pluralize called with vec" << std::endl;
return words;
}

当使用字符串作为参数调用方法复数时,它按预期工作:更改传递的单词的值。 当使用 vec 调用时,它不会更改传递的字符串的值。 这些是我的测试用例:

代码适用于这些测试用例:

SECTION("Respects capitalization") {
    REQUIRE(pluralize("Car") == "Cars");
    REQUIRE(pluralize("Mouse") == "Mice");
    REQUIRE(pluralize("German") == "Germans");
    }

这些测试用例失败了:

REQUIRE(
        pluralize({"Car", "Mouse", "German"}) == make_vec({"Cars", "Mice", "Germans"})
    );

【问题讨论】:

    标签: c++ string vector reference constants


    【解决方案1】:

    您不能修改words,因为它是const
    您没有注意到这一点,因为您没有修改它 - for (auto word : words) 中的推导类型是 std::string,而不是 std::string&amp;

    例如,您可以复制输入并修改您的副本:

    std::vector<std::string> pluralize(std::vector<std::string> const& words)
    {
        std::vector<std::string> plurals = words;
        for (auto& word : plurals) {
            word = pluralize(word);
        }
        return plurals;
    }
    

    或循环收集复数词:

    std::vector<std::string> pluralize(std::vector<std::string> const& words)
    {
        std::vector<std::string> plurals;
        for (const auto& word : words) {
            plurals.push_back(pluralize(word));
        }
        return plurals;
    }
    

    或使用std::transform:

    std::vector<std::string> pluralize(std::vector<std::string> const& words)
    {
        std::vector<std::string> plurals;
        std::transform(words.begin(), words.end(), std::back_inserter(plurals), pluralize);
        return plurals;
    }
    

    或其他一些解决方案...

    【讨论】:

    • 感谢回复,std::transform 看起来是个有趣的解决方案
    【解决方案2】:

    问题出在这里:

    for (auto word : words) {
        word = pluralize(word);
    }
    

    这里的变量word是一个字符串。您正在更改该值,但这不会更改向量中的单词。尝试使用参考:

    for (auto& word : word) {
        word = pluralize(word);
    }
    

    auto 不推断引用。

    编辑:您不能修改向量中的元素,因为您将它作为对 const 的引用。修复它的一种方法是获取向量的副本。最简单的方法是将函数的签名修改为按值传递:

    std::vector<std::string> pluralize(std::vector<std::string> words) {
        for (auto& word : words) {
            word = pluralize(word);
        }
        return words;
    }
    

    【讨论】:

    • 我试过了,但它给了我一个错误:没有可行的重载'=',我猜这是因为 const 关键字。
    • @YevgenPonomarenko 然后不要通过 reference-to-const 传递向量。按值传递。
    猜你喜欢
    • 2012-02-13
    • 2014-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-15
    • 1970-01-01
    相关资源
    最近更新 更多