Edw*_*vis 7 c++ syntax programming-languages semantics
编辑:这个问题更多的是关于语言工程而不是C++本身.我以C++为例来展示我想要的东西,主要是因为我每天都在使用它.我并不想知道它是如何工作的C++,但打开它如何的讨论会来完成.
这不是它现在的工作方式,这就是我希望它可以完成的方式,这肯定会打破C兼容性,但这就是我认为extern"C"的全部意义.
我的意思是,在您现在声明的每个函数或方法中,您必须显式写入该对象将通过引用在其上添加前缀作为参考运算符.我希望每个非POD类型都会通过引用自动发送,因为我使用了很多,实际上对于每个大小超过32位的对象,这几乎是我的每一类.
让我们举例说明它是如何做的,假设a,b和c为类:
class example {
public:
int just_use_a(const a &object);
int use_and_mess_with_b(b &object);
void do_nothing_on_c(c object);
};
现在我想要的是:
class example {
public:
int just_use_a(const a object);
int use_and_mess_with_b(b object);
extern "C" void do_nothing_on_c(c object);
};
现在,do_nothing_on_c()的行为就像今天一样.
至少对我来说这会很有趣,感觉更清楚,而且如果你知道每个非POD参数都是通过引用而来的,我相信如果你必须明确地声明它,那么错误将是相同的.
对于这种变化的另一种观点,来自C的人,参考运算符在我看来是一种获取变量地址的方法,这就是我用来获取指针的方式.我的意思是,它是相同的运算符,但在不同的上下文中具有不同的语义,对你来说这不是觉得有点不对吗?
pae*_*bal 15
我猜你错过了C++和C++语义的观点.你错过了C++在传递(几乎)所有东西时是正确的事实,因为它是在C中完成的.总是.但不仅仅是在C中,我将在下面向您展示......
在C中,一切都按值传递.通过复制它们的值来传递"原语"和"POD".在您的函数中修改它们,原始文件将不会被修改.尽管如此,复制一些POD的成本可能并非琐碎.
当您使用指针表示法(*)时,您不会通过引用传递.你传递了一份地址副本.哪个或多或少相同,只有一个微妙的区别:
typedef struct { int value ; } P ;
/* p is a pointer to P */
void doSomethingElse(P * p)
{
p->value = 32 ;
p = malloc(sizeof(P)) ; /* Don't bother with the leak */
p->value = 45 ;
}
void doSomething()
{
P * p = malloc(sizeof(P)) ;
p->value = 25 ;
doSomethingElse(p) ;
int i = p->value ;
/* Value of p ? 25 ? 32 ? 42 ? */
}
Run Code Online (Sandbox Code Playgroud)
p->值的最终值为32.因为p是通过复制地址的值来传递的.因此原始的p没有被修改(并且新的p被泄露).
对某些人来说这可能是令人惊讶的,但在Java中,一切都是按价值复制的.上面的C示例将在Java中给出完全相同的结果.这几乎就是你想要的,但是你不能像在C中一样容易地传递原语"by reference/pointer".
在C#中,他们添加了"ref"关键字.它或多或少像C++中的引用一样.关键是,在C#上,你必须在函数声明和每次调用中都提到它.我想这不是你想要的,再次.
在C++中,几乎所有东西都是通过复制值传递的.当你只使用符号的类型时,你正在复制符号(就像在C中完成一样).这就是为什么当你使用*时,你传递的是符号地址的副本.
但是当你使用&时,假设你正在传递真实对象(无论是struct,int,pointer,等等):引用.
很容易将它误认为是语法糖(即,在幕后,它像指针一样工作,并且生成的代码与指针一样).但...
事实是,参考不仅仅是语法糖.
因此,参考文献具有两全其美的优点.
让我们看一下C示例,但在doSomethingElse函数上有一个C++变体:
struct P { int value ; } ;
// p is a reference to a pointer to P
void doSomethingElse(P * & p)
{
p->value = 32 ;
p = (P *) malloc(sizeof(P)) ; // Don't bother with the leak
p->value = 45 ;
}
void doSomething()
{
P * p = (P *) malloc(sizeof(P)) ;
p->value = 25 ;
doSomethingElse(p) ;
int i = p->value ;
// Value of p ? 25 ? 32 ? 42 ?
}
Run Code Online (Sandbox Code Playgroud)
结果是42,旧p被泄露,取而代之的是新p.因为,与C代码不同,我们不会传递指针的副本,而是传递指针的引用,即指针本身.
使用C++时,上面的例子必须清楚明了.如果不是,那么你就错过了什么.
C++是pass-by-copy/value,因为它是一切正常的方式,无论是在C语言,C#还是在Java中(即使在JavaScript ... :-p ...中).和C#一样,C++有一个引用运算符/关键字作为奖励.
现在,就我所理解的而言,你可能正在做我称之为半开玩笑的C +,即具有一些有限的C++特性的C语言.
也许你的解决方案是使用typedef(它会激怒你的C++同事,看看被无用的typedef污染的代码......),但这样做只会混淆你真正缺少C++的事实.
正如在另一篇文章中所说,你应该将你的思维方式从C开发(无论如何)转变为C++开发,或者你应该转向另一种语言.但是不要继续用C++函数编写C语言编程,因为通过有意识地忽略/混淆你使用的习语的力量,你将产生次优的代码.
注意:除了原语外,不要复制任何其他内容.你将从它的OO容量中阉割你的函数,而在C++中,这不是你想要的.
这个问题有所修改(参见https://stackoverflow.com/revisions/146271/list).我让我的原始答案,并回答下面的新问题.
您如何看待C++上的默认传递引用语义?就像你说的那样,它会破坏兼容性,并且你将对原语(即内置类型,仍将通过副本传递)和结构/对象(将作为引用传递)进行不同的传递.你必须添加另一个运算符来表示"按值传递"(extern"C"非常糟糕,已经用于其他完全不同的东西).不,我真的很喜欢今天用C++完成它的方式.
[...]参考运算符在我看来是一种获取变量地址的方法,这就是我用来获取指针的方式.我的意思是,它是相同的运算符,但在不同的上下文中具有不同的语义,对你来说这不是觉得有点不对吗?是的,不是.当与C++流一起使用时,运算符>>改变了它的语义.然后,您可以使用operator + =来替换strcat.我猜运算符已被使用,因为它的意思是"与指针相反",并且因为它们不想使用另一个符号(ASCII是有限的,并且范围运算符::以及指针 - >显示其他几个符号是可用的).但是现在,如果&困扰你,&&会真的让你感到不安,因为他们在C++ 0x中添加了一元&(一种超级引用......).我自己还没有消化它......