为什么 std:set(只有一个冒号)可以编译通过?

69

I accidentally wrote

std::set<string> keys;

作为:

std:set<string> keys;

但是奇怪的是,Visual Studio 2013仍然可以编译。

为什么会这样呢?

实际上,keys不仅被定义了,而且后来还被用作一组字符串,例如:

if(keys.find(keystr)==keys.end()){
    keys.insert(keystr);
    toret.push_back(tempv);
}

14
"std:" 被解释为 goto 语句中的一个“标签”。请参阅:https://en.cppreference.com/w/cpp/language/goto - Sandburg
2个回答

104
在块级作用域中,一个标识符后跟一个冒号会引入一个标签。因此,您的语句等效于:

在块级作用域中,标识符后面跟着一个冒号表示引入了一个标签。因此,您的语句与以下语句等效:

set<string> keys;

除了带有标签std的标签,可以通过语句goto std;跳转到该标签,其他与普通标签相同。

由于某种原因,编译器知道set这个名称 - 也许您使用了using namespace std;using std::set;等等,或者您定义了自己的set类型。


46
避免使用 using namespace std;using std::set; 的另一个原因是这样做可能会导致命名冲突。 - R Sahu
34
反对使用using namespace std/using std::set有很好的论据,但我不确定这是其中之一……通常的主要论点是命名空间用于防止冲突,但如果有一个非 std 的“set”会发生冲突,那么 std:set<...>可能是有效的。普遍做法是将任何此类 using 声明限制在另一个命名空间/函数中,但这个问题同样可能发生在该范围内。我更容易想到的是,在重写std::chrono::high_resolution_clock等内容时出现打字错误等问题,而不是这种标签打字错误(这是我见过的第一个这样的情况)。 - John P

11
在第二种情况下,std是一个标签。它与在case语句中拼写default有误相同。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接