4

我有以下代码-:

int main()
{
    set<string> s;
    s.insert( "asas" );
    s.insert( "abab" );

    for ( auto item : s )
    {
        cout << item << "\n";
        reverse( item.begin(), item.end() );
    }

    cout << "\n";

    for ( auto item : s )
    {
        cout << item << "\n";
    }
}

输出 -:

abab
asas

abab
asas

该集合的元素根本没有被reverse()函数修改。
我怀疑集合中的元素根本无法修改。但是,如果是这种情况,为什么编译器本身不首先给出错误?

-std=c++14在 Windows 7 上使用带有标志的 TDM-GCC 4.9.2。

4

3 回答 3

10

a 的元素std::setconst。如果您想改变元素,您需要进行插入和删除以使容器处于您想要的状态。

在您的代码示例中:

for (auto item : s)

被翻译成类似的东西:

for (auto iter = s.begin(); iter != s.end(); ++iter)
{
    auto item = *iter; // Copy!
    // loop body
}

循环归纳变量item是中的元素的副本set,而不是对 中的实际元素的引用set。结果,set没有改变。要更改集合,您需要调用 的成员函数set,例如inserterase

更改item&item在这里无济于事;如果你这样做,你会得到一个编译时错误,因为集合的元素是 const,所以你不能应用reverse它们。

于 2015-07-01T06:25:23.253 回答
4

这个基于范围的循环会复制集合中的每个元素:

for ( auto item : s )

这就是为什么您可以item在循环中进行修改而不会触发编译器错误的原因。

如果你想修改容器的元素,你需要一个参考。使用它确实会导致编译器错误,因为无法修改集合的元素:

for ( auto& item : s )
{
  // s is a set. You cannot modify item
于 2015-07-01T06:22:50.253 回答
1

std::set 中的对象是 const,因为它们被用作键。所以你不能像这样修改集合中的对象。

于 2015-07-01T06:51:13.393 回答