编辑:这个问题更多的是语言的工程于C++本身。我用C++作为一个例子显示什么我想要的,主要是因为我每天使用它。我不想知道它是如何工作上的C++但是打开一个讨论它如何 可能 要做。

那不是它的工作方式,现在,这就是我 希望 这是可以做到的,这将打破C兼容性肯定的,但是我认为外部"C"是所有有关。

我的意思是,在每一个功能或方法,你声明,现在你必须明确写信对象将发送的通过引用的前缀准操作员。我希望,每一个非POD类型将自动发送的参考,因为我用了很多,实际上对每个对象是超过32位的大小,并几乎每一类地雷。

让我们举例说明它如何是正确的,现在,假设 一个, bc 要类别:

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,参考操作者似乎对我的方式获得的可变 地址, 那是我用来获取指针。我的意思是,它是相同的操作者,但不同的语义上的不同情况下,不觉得有点不对的你也是?

有帮助吗?

解决方案

我猜你缺点的C++、C++的语义。你错过的事实 C++是正在通过(几乎)的一切的价值,因为这是它的完成。总是.但是,不仅在C,作为我会告诉你下面...

参语义上的C

在C,一切都过去了价值。"元"和"豆"是通过了复制自己的价值。修改他们在你的功能,并将原来不会进行修改。然而,成本的复制一些荚可能是非微不足道的。

当你使用的指针符号的(*),你不通过参考。你传递一个复制的地址。这或多或少相同,但一个细微区别:

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 ? */
}

最后值的p->的价值为32。因为p通过了复制的价值的地址。所以原来的p不是修改(和新的被泄漏).

参语义上Java和C

这可奇怪的,对于一些,但在爪哇,一切都是复制的价值,太多。C如上所述将得到完全相同的结果。这几乎是你想要什么,但你也不能够通过原始的"参考/指针"作为容易,因为在C。

在C#他们加入了"参考"的关键词。它的工作原理或多或少像引用C++。这一点是,对,你有提到它在功能宣言》,并在每个呼吁。我猜测这是不是你想要的,一次。

参语义上的C++

C++中,几乎一切都是通过复制的价值。当你用的是什么,但这种类型的符号,你在复制的符号(好像是在C)。这就是为什么,当你使用的*,你穿的副本,该地址符号。

但是当你使用&,然后假设你是通过真正的对象(如是结构,int、指针无论):参考。

很容易把它作为syntaxic糖(即,在幕后,它就像一个指针,并产生的代码是一样的使用为指针)。但是...

事实是,参考多syntaxic糖。

  • 不同的指针,其授权的操纵的对象,如果上堆。
  • Unline指针,当associatied与const关键词,它授权隐含的推动从一种类型的另一(通过构造,主要是).
  • 不同的指针,象征不应该是无/无效。
  • 不同的是"通过拷贝",你不是无用的开支时间复制的对象
  • 不同的是"通过复制",可以用它作为一个[了]的参数
  • 不同的是"通过复制",可以使用的充分范围内的面向对象用C++(即你通过一个充分的对象为一个功能等待一个接口)。

因此,引用的有两个最好的世界。

让我们看看C例,但是用C++的变化对doSomethingElse功能:

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 ?
}

结果是42,老p被泄露,取而代之的新的p.因为,与C码,我们不通过一个复制的指针,而参考的指针,即,指针本身。

工作时,使用C++,上述例子必须cristal清楚。如果不是,那么你就丢失的东西。

结论

C++是通过由副本/价值,因为它是一切工作,它在C,C#或在Java(甚至在JavaScript...:-p...).像C#、C++基准操作员/关键词, 作为奖金.

现在,据我了解,您也许在做什么,我叫半jockingly C+, ,也就是说,C与一些有限C++的功能。

也许是你解决方案使用的类型定义(这将激怒你C++的同事们,虽然看到码污染的无用typedef...),但这样做只会混淆事实上你们真的缺少C++在那里。

正如所述在另一篇文章你应该改变你的心态从C开发的(任何)至C++发展,或者你也许应该搬到另一种语言。但是,不要保持程序的C的方式使用C++的功能,因为通过有意识地忽视/混淆权力的习惯用语使用时,你就会产生次优的代码。

注:不过复制任何东西比元。你会阉了你能从其OO能力,并在C++,这不是你想要什么。

编辑

问题是 有些 修改(见 https://stackoverflow.com/revisions/146271/list ).我让我原来的答案,并回答的新问题如下。

你怎么想的默认通过参考的语义上的C++? 就像你说的,它将破坏兼容性,你就会有不同的通过为元(即建造类型,这将仍然是通过复制)和结构的对象(这将是通过为参考文献)。你就必须增加另一个操作者的意思是"通过价值"(外部"C"是相当可怕的,并且已经用于别的东西相当不同)。没有,我真的很喜欢它的方式是今天在C++。

[...]基准操作者似乎对我的方式获得的可变地址,这就是我用来获取指针。我的意思是,它是相同的操作者,但不同的语义上的不同情况下,不觉得有点不对的你也是? 是的,没有。操作员>>改变它的语义时,使用C++流,太多。然后,你可以使用的操作员+=替换strcat.我猜员&有使用,因为其意义为"相反的指针",并且因为它们没有想要使用的又一个符号(ASCII是有限的,且范围operator::以及指针>显示,其他几个符号是可用的).但是现在,如果&打扰你,&&将真的失去勇气,你,因为他们加入一个一元&&C++0x(一种超参考...).我还没来得及消化它自己...

其他提示

一个完全改变代码段意义的编译器选项对我来说听起来真的很糟糕。要么使用C ++语法,要么找到不同的语言。

我宁愿不要通过将每个(非限定)参数作为参考来滥用引用。

引用加入C ++的主要原因是 to支持运营商重载;如果你想要“传递参考”语义学,C有一种非常合理的方式:指针。

使用指针清楚地表明你想改变指向对象的值,并且可以通过查看函数调用来看到这一点,你不必查看函数声明来查看它是否正在使用参考

另外,请参阅

  

我确实想改变这个论点,   我应该使用指针还是应该使用   参考?我不知道强者   逻辑原因。如果通过``不是   对象''(例如空指针)是   可以接受,使用指针制作   感。我的个人风格是用一个   当我想修改一个指针   对象,因为在某些情况下   更容易发现一个   修改是可能的。

来自同一个常见问题解答

是的,我认为这是一个非常令人困惑的超载。

这就是微软对这种情况所说的话:

  

不要将引用声明与使用address-of运算符混淆。当&标识符前面有一个类型,例如int或char,然后标识符被声明为对类型的引用。当&标识符前面没有类型,用法是address-of运算符。

我在C或C ++方面并不是很出色,但是我更加头疼,整理了*和&的各种用途。两种语言都比我在汇编程序中编码。

最好的建议是养成思考你真正想要发生的事情的习惯。当你没有复制构造函数(或者不想使用它)时,通过引用传递是很好的,并且它对于大对象来说更便宜。然而,在课堂外感受到参数的突变。您可以通过 const 引用 - 然后没有突变,但您无法进行本地修改。对于在函数中应该只读的廉价对象传递const by-value,并在需要可以进行本地修改的副本时传递非const by-value。

每个排列(按值/按引用和常量/非常量)具有明显不相等的重要差异。

当您传递值时,您正在将数据复制到堆栈。如果您为要传递的结构或类定义了operator =,则会执行该操作。我所知道的没有编译器指令可以消除所提出的更改本身会导致的隐含语言混淆的严峻考验。

一个常见的最佳实践是通过const引用传递值,而不仅仅是通过引用传递值。这可确保在调用函数中无法更改该值。这是const-correct代码库的一个元素。

完全const-correct代码库更进一步,将const添加到原型的末尾。考虑一下:

void Foo::PrintStats( void ) const {
   /* Cannot modify Foo member variables */
}

void Foo::ChangeStats( void ) {
   /* Can modify foo member variables */
}

如果要将Foo对象传递给函数(以const为前缀),则可以调用PrintStats()。编译器在调用ChangeStats()时会出错。

void ManipulateFoo( const Foo &foo )
{
    foo.PrintStats();  // Works
    foo.ChangeStats(); // Oops; compile error
}

老实说,我认为整个传递价值/通过C ++中的参考思想传递是误导。 Everything 是按值传递的。你有三种情况:

  1. 传递变量的本地副本

    void myFunct(int cantChangeMyValue)
    
  2. 将指针的本地副本传递给变量

    void myFunct(int* cantChangeMyAddress) {
        *cantChangeMyAddress = 10;
    }
    
  3. 你传递一个'引用'的地方,但是通过编译器魔法就像你传递一个指针一样,每次只是取消引用它。

    void myFunct(int & hereBeMagic) {
        hereBeMagic = 10; // same as 2, without the dereference
    }
    
  4. 我个人觉得很难记住,一切都是通过价值传递的。在某些情况下,该值可能是一个地址,允许您更改函数外部的内容。

    你的建议是不允许程序员做第1号。我个人认为拿掉那个选项是个坏主意。 C / C ++的一个主要优点是具有细粒度的内存管理。让一切都通过引用传递只是试图使C ++更像Java。

有些事情不清楚。当你说:

  

int b(b& param);

你想要第二个'b'是什么意思?你忘记介绍一种类型吗?你是否忘了对第一个'b'做出不同的写作?难道你不觉得写下这样的东西很清楚:

class B{/*something...*/};
int b(B& param);

从现在开始,我想你的意思是我写的。

现在,您的问题是“您认为编译器不会将非POD的每个pass-by-value视为pass-by-ref吗?”并不会更好。 第一个问题是它会破坏你的合同。我想你的意思是传递CONST参考,而不仅仅是参考。

现在你的问题被简化为这个:“你知道是否有一些编译器指令可以按值优化函数调用?”

现在的答案是“我不知道”。

如果你开始混合所有可用的参数及其const变量,我认为c ++变得非常混乱。

它会迅速失控,无法完成所有复制构造函数调用,所有解除引用的重载等等。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top