C++的隐藏特性是什么?

114

在讨论“隐藏功能”问题时,没有关于C++的爱吗?我想我应该提出这个问题。C++有哪些隐藏功能?


@Devtron - 我曾见过一些被当作功能出售的神奇漏洞(如意外行为)。事实上,游戏行业现在正在尝试让这种情况发生,并称之为“自发游戏”(此外,请查看《灵能追击》中的“TK冲浪”,它最初只是一个漏洞,但他们将其保留并成为了游戏中最好的功能之一,在我看来)。 - Grant Peters
5
并不是很多人从头到尾读过786页的ISO C++标准,但我想你肯定做到了,并且还记住了全部内容,对吗? - j_random_hacker
2
@Laith,@j_random:请查看我的问题“程序员的笑话是什么,我如何识别它,以及适当的回应”在http://stackoverflow.com/questions/1/you-have-been-link-rolled。 - Roger Pate
请查看 http://meta.stackexchange.com/questions/56669/should-hidden-features-of-x-be-removed-closed-locked,http://meta.stackexchange.com/questions/57226/should-we-have-a-list-of-x-close-reason 以及相关的 Meta 帖子。 - Roger Pate
64个回答


3

我不确定是否涉及隐藏,但从规范中仅仅阅读可能无法发现一些有趣的 '技巧'


即使晚了55分钟,应该与https://dev59.com/b3VD5IYBdhLWcg3wI3-L#76058中的重复内容合并/组合,或者仅删除以支持另一个。 - Roger Pate
请不要使用达夫设备。 - Billy ONeal

3

有很多"未定义行为"。通过阅读好书和标准,您可以学习如何避免它们。


2
这怎么算是一个特性呢?有两种不同的方式可以考虑它作为一个特性,但我在这里看不到任何迹象。因为含糊不清,扣1分。 - Roger Pate
或者你可以学会接受它们,这是一件好事。 - Thomas Eding

3

大多数C++开发人员忽略了模板元编程的威力。请查看Loki Library。它广泛使用模板元编程实现了诸如类型列表、函数对象、单例模式、智能指针、对象工厂、访问者和多方法等多个高级工具(来自wikipedia)。在很大程度上,你可以将这些视为“隐藏”的C++特性。


我们不会忽视它,而是避之唯恐不及... - Jimmy J
这是从https://dev59.com/b3VD5IYBdhLWcg3wI3-L#76058复制的模板元编程模板。这些示例已合并到该答案中,因此可以删除此副本。 - Roger Pate

3
  • 类方法指针
  • "typename"关键字

2
  1. map::insert(std::pair(key, value)); doesn't overwrite if key value already exists.

  2. You can instantiate a class right after its definition: (I might add that this feature has given me hundreds of compilation errors because of the missing semicolon, and I've never ever seen anyone use this on classes)

    class MyClass {public: /* code */} myClass;
    

2

请注意自由函数指针和成员函数指针初始化之间的区别:

成员函数:

struct S
{
 void func(){};
};
int main(){
void (S::*pmf)()=&S::func;//  & is mandatory
}

和自由函数:

void func(int){}
int main(){
void (*pf)(int)=func; // & is unnecessary it can be &func as well; 
}

感谢这个冗余的 &,你可以在不使用它的情况下在链中添加流操作符 - 这些是自由函数:
cout<<hex<<56; //otherwise you would have to write cout<<&hex<<56, not neat.

2

main()函数不需要返回值:

int main(){}

这是最短的有效C++程序。


从技术上讲,不是这样的,因为你需要一个换行符才能使其有效:p - Kaz Dragon
1
@Kaz:换行符已经存在了,点击“编辑”以查看源代码。 :) - Roger Pate

1
我觉得递归模板实例化非常酷:
template<class int>
class foo;

template
class foo<0> {
    int* get<0>() { return array; }
    int* array;  
};

template<class int>
class foo<i> : public foo<i-1> {
    int* get<i>() { return array + 1; }  
};

我曾使用它生成一个类,其中包含10-15个函数,这些函数返回指向数组各个部分的指针,因为我使用的API需要每个值的一个函数指针。

即编程编译器通过递归生成一堆函数。简单易行。:)


1

间接转换惯用语

假设您正在设计一个智能指针类。除了重载运算符*和->之外,智能指针类通常还定义了一个转换运算符以将其转换为bool类型:

template <class T>
class Ptr
{
public:
 operator bool() const
 {
  return (rawptr ? true: false);
 }
//..more stuff
private:
 T * rawptr;
};

将smart pointers转换为bool,使得客户端能够在需要bool操作数的表达式中使用它们。
Ptr<int> ptr(new int);
if(ptr ) //calls operator bool()
 cout<<"int value is: "<<*ptr <<endl;
else
 cout<<"empty"<<endl;

此外,在条件声明中需要将隐式转换为bool,例如:
if (shared_ptr<X> px = dynamic_pointer_cast<X>(py))
{
 //we get here only of px isn't empty
} 

哎呀,这个自动转换打开了一个不受欢迎的惊喜之门:
Ptr <int> p1;
Ptr <double> p2;

//surprise #1
cout<<"p1 + p2 = "<< p1+p2 <<endl; 
//prints 0, 1, or 2, although there isn't an overloaded operator+()

Ptr <File> pf;
Ptr <Query> pq; // Query and File are unrelated 

//surprise #2
if(pf==pq) //compares bool values, not pointers! 

解决方案:使用“间接转换”习语,通过从指向数据成员[pMember]的指针到bool的转换,使只有1个隐式转换,这将防止上述意外行为:pMember->bool而不是bool->其他内容。

但也请查看safe bool idiom - sehe

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