定义一个像 Python "with" 语句一样工作的 C 宏有什么缺点?
What are the downsides to defining a C macro that works like the Python "with" statement?
在摆弄了一些C预处理器之后,我想到了一种类似于python的控制结构的方法,定义如下:
#define with(var) for(int i##__LINE__=0;i##__LINE__<1;)for(var;i##__LINE__<1;++i##__LINE__)
示例用法:
#include <cstdio>
#include "FileClass.hpp"
#include "with.hpp"
int main(){
with(FileClass file("test.txt")){
printf("%sn",file.readlines().c_str());}
return 0;}
这个想法是双嵌套的for循环有一个外部混淆的迭代变量,该变量在内部循环中增加一次以打破它。这会导致以下代码被执行一次,其中var在其作用域中。
这有什么缺点吗?如果我对迭代变量进行了足够的混淆,就几乎不会有名称冲突的可能性,它只使用标准的预处理器特性,似乎没有任何适得其反的可能性,并且非常容易理解。
这似乎好得令人难以置信——有什么原因没有在所有地方使用吗?
有什么原因没有在所有地方使用?
是的,c++不是Python,如果我正确理解你的代码,这是完全相同的:
{
FileClass file("test.txt");
printf("%sn", file.readlines().c_str());
}
那么,缺点是什么呢?不自然的语法,使用预处理器进行代码混淆,用更多的样板代码实现与上面相同的功能,以及统一使用c++。足够了吗?
c++有非常重要的值类型和基于作用域的堆栈变量确定性销毁的概念。这导致了非常重要的习惯用法,如SBRM(范围约束资源管理,也称为RAII)。
它在精神上类似于用c编写的原始Bourne shell中使用的宏。它们旨在提供类似于Algol 68的语法,Algol 68显然是Bourne首选的语言。
来自http://minnie.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/sh/mac.h:
的小样本#define IF if(
#define THEN ){
#define ELSE } else {
#define ELIF } else if (
#define FI ;}
结果往往是C程序员(他们必须熟悉您的宏以及C本身的语法)或Algol 68,或者您的情况下的Python程序员难以阅读的代码。
如果我读了一个使用with()
宏的c++程序,如果没有(a)意识到with()
是一个宏(宏通常都是大写的名字),(b)跟踪宏的定义,(C)破译由扩展宏产生的相当奇怪的C代码,我就无法真正理解它在做什么。这是假设我没有陷入这样的陷阱,认为它是一个特定于编译器的扩展,或者C有一个我不知道的with
语句。
或者,如果我碰巧理解Python with
语句,那么我仍然需要(a)意识到您的with()
宏旨在模仿Python with
语句,并且(b)相信您能够正确使用。
多年前,我认为这是:
#define ever ;;
...
for (ever) { ... }
非常聪明。我仍然认为这很聪明;但我不再认为聪明是一件好事。
这似乎好得令人难以置信——有什么理由不这样做吗使用无处不在?
当然,这是一个很好的结构,对你来说很好,但是团队中的其他人呢?未来的你——六个月后——不记得你写的那些可爱的宏了怎么办?
简而言之,像这样的语法练习在家里是很好的练习,但在协作环境中是很糟糕的,甚至对于将来你一个人维护的代码来说也是如此。坚持最佳实践,你的代码将更容易维护和理解。
这并不是说你不应该在家里做这种事情。做你喜欢的事,让你的大脑保持灵活。但是不要在生产中使用你的热身练习!这真的是"with"吗?Python中"with"的最大优点是它与上下文管理器一起工作,上下文管理器负责自动关闭/释放/解锁/取消分配"with"语句中的变量。在c++中,有一些标准方法可以做到这一点。例如,auto_ptr
将负责自动删除分配了new的指针。学习这些标准成语,然后再重新定义它们。
这样做的一个明显的缺点是没有人能够读懂你的面条式的python -in- c++代码。祝你在维护代码时好运。
- QSqlquery prepare()和bindvalue()不工作
- 导入库可以跨dll版本工作吗
- 以螺旋方式打印矩阵的程序.(工作不好)
- 对象指针在c++中是如何工作的
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- C++为线程工作动态地分割例程
- 为什么我的 std::ref 无法按预期工作?
- 布尔比较运算符是如何在C++中工作的
- SampleConsensusPrerejective(ext.RANSAC)是如何真正工作的
- 不确定要在我的main中放入什么才能使我的代码正常工作
- 为什么std::condition_variable notify_all的工作速度比notify_one快(对于随机请
- <<操作员在下面的行中工作
- 有人能解释一下为什么下界是这样工作的吗C++的
- ExtractIconEx:可以工作,但偶尔会崩溃
- C++中的memset函数工作不正常
- 当我在第一个循环中使用"auto"时,它工作正常,但是使用"int"它会给出错误,为什么?
- 链表c++插入,所有情况都已检查,但没有任何工作
- 定义一个像 Python "with" 语句一样工作的 C 宏有什么缺点?