代码之家  ›  专栏  ›  技术社区  ›  pankajt

C++参考文献与Java参考文献

  •  11
  • pankajt  · 技术社区  · 17 年前

    //C++示例

    #include <iostream>
    using namespace std;
    
    int doHello (std::string&);
    int main() {
        std::string str1 = "perry";
        cout << "String=" << str1 << endl;
        doHello(str1);
        cout << "String=" << str1 << endl; // prints pieterson
        return 0;
    }
    
    int doHello(std::string& str){
        str = "pieterson";
        cout << "String=" << str << endl;
        return 0;
    }
    

    在上述情况下,如预期,当str引用被修改时,字符串“str1”引用被修改。

    /java实例

    public class hello {
    
        public static void main(String args[]){
            String str1 = "perry";
            System.out.println("String=" + str1);
            doHello(str1);
            System.out.println("String=" + str1); // does not prints pieterson
        }
    
        public static void doHello(String str){
            str = "pieterson";
            System.out.println("String = " + str);
        }
    }
    

    在爪哇中,String STR和String STR1是两个不同的对象,它们最初引用同一个字符串,所以当我们改变DOHELLO()中的STR引用时,STR1引用没有改变。

    如何在Java中实现具有字符串、集合(如列表、向量、其他对象)的C++风格功能。

    更新:

    谢谢乔恩的精彩解释,我相信任何Java初学者肯定会遇到这个问题。 让我解释一下在使用列表时遇到的问题。

    //bad doHello() 
    
    void doHello(List inputList) { 
        inputList = getListFromAnyFunction(); // wrong, didnt work 
    } 
    
    // good doHello 
    
    void doHello(List inputList) { 
        inputList.addAll(getListFromAnyFunction()); // worked 
    }
    

    感谢鲍威尔和哈什的解释和代码示例。

    4 回复  |  直到 9 年前
        1
  •  12
  •   Jon Skeet    17 年前

    Java根本没有传递引用(您在C++代码中使用的)。引用按值传递。(的值 str 和 str1 对象根本不是对象,它们是引用——这真的有助于将这两个概念分开。)

    通常,如果您需要:

    str1 = doHello(str1);
    

    请注意,字符串与list等稍有不同,因为字符串是不可变的。要修改集合(任何可变集合),不需要创建新集合,只需修改 对象 通过原始参考:

    public static void addHello(List<String> items)
    {
        items.add("Hello");
    }
    

    你可以这样称呼它:

    List<String> list = new ArrayList<String>();
    addHello(list);
    System.out.println(list.get(0)); // "Hello"
    

    变异现有的 对象 以及将变量的值更改为引用 不同的 目标至关重要。如果您想让现有的集合单独存在并创建一个新的集合,则必须显式地这样做:

    public static List<String> withHello(List<String> items)
    {
        List<String> newList = new ArrayList<String>(items);
        newList.add("Hello");
        return newList;
    }
    

    你可以这样称呼它:

    List<String> empty = new ArrayList<String>();
    List<String> newList = withHello(empty);
    System.out.println(empty.size()); // Prints 0
    System.out.println(newList.size()); // Prints 1
    

    这能满足你所需要的一切吗?

        2
  •  13
  •   Steve Powell    17 年前

    参数传递、引用调用和值调用(简短回答)

    在C++中有两个参数传递窗体, 按值调用 和 参考呼叫 . (更好的名字是 按值调用 是 按新值调用 但是我离题了。)

    在Java程序中,所有参数都通过。 按价值 . 有人认为Java是通过引用传递对象的,但是它们错了。 参考值 但这根本不是一回事。]

    这个 价值 Java对象(以及通过的对象)是 指针 对对象(令人困惑地,但精确地称为对象的引用),并调用Java对象方法,例如 obj.meth() ,取消引用 指针 价值 obj 在调用在那里找到的对象的方法之前。

    在C++中,相同的调用看起来像: obj->meth() .

    如果操作对象(例如,通过调用它的方法)作为参数传递给爪哇中的方法,则可以修改该对象,如果调用方仍有变量保存该对象,则可以看到这些更改。如果只分配给(本地)参数变量,只需更新存储在本地变量中的指针,对象不会受到影响,调用方不会注意到这一点。

    所以,你的问题的简短答案是Java通过值传递,而C++中的引用调用机制在Java中是不可用的。

    参数、变量和按值调用(长答案)

    为了理解这里发生的事情,我们需要更深入地了解变量和参数传递的机制。

    变量

    一般来说,编程语言中的变量是与值关联的标识符。表示在 运行时 (我们在这里忽略宏变量、被“编译掉”的常量等等)必须 二 与它们相关联的值。下面是一个例子,解释了为什么:

    int a = 0;
    a = a + 1;
    

    a 是变量,并且在行中 a = a + 1; 它是指 两次 . 一次,(在 右手边 的 = 价值 0 是指曾经 左手边 的 = ) 位置 价值的 一 意思是(也就是说, 其中的整数值 一 存储 )只有通过访问该位置,程序才能 更新 其中包含的值。

    与变量关联的这两个值称为 R值 以及 L值 . (这些名字是克里斯托弗·斯特拉奇发明的;我是一个粉丝。)语言中的其他结构根据上下文指这些值中的一个或其他值。例如:

    a[x-1] = x;
    

    指的是 x 两次(即使其中一次在 = ,但只有l值 一 (或至少一个数组元素 一 )

    在大多数编程语言中,我们显式地操纵变量的r值,并让编译器(从程序的形式)为我们自动管理l值。我们必须对它们有一点了解(在C语言中,特别是在数组中,我们假设了很多关于L值的东西),但大多数时候我们不需要知道力学原理。

    按值调用

    看这个电话:

    int p=1;
    obj.meth(p);
    …
    void meth(int a) {…a…}
    

    这里的参数发生了什么?首先是的r值 p 然后,当 meth 是“entered”,一个新变量 一 是构造的。它被赋予一个新的L值(这个位置通常在某种类型的堆栈上),参数的R值存储在这个位置上。

    现在,什么时候 一 出现在 甲基 它的r值与 磷 有(最初)和一个新的L值。改变到 一 的r值与变量没有区别 磷 . 这叫做 按值调用 (更恰当地说, 按新值调用 )

    参考呼叫

    请看这个C++调用:

    int p=1;
    obj.meth(p);
    …
    void meth(int& a) {…a…}
    

    这里是参数的l值 磷 当变量 一 其结构为_给定__ 相同的 L值AS 磷 . 然后使用任何 一 体内 甲基 就像是 磷 . 例如,赋值将更改 磷 以及 一 .

    Java不这样做。

        3
  •  1
  •   jrharshath    17 年前

    你用Java编写的代码相当于这个C++代码:

    int main() {
        std::string *s1;
        s1 = new std::string("perry");
        std::cout << s1->c_str() << std::endl;
        doMojo( s1 );
        std::cout << s1->c_str() << std::endl; // not pieterson
    }
    void doMojo( std::string *str ) {
        str = new std::string("pieterson");
        std::cout << str->c_str() << std::end;
    }
    

    也许现在你看到发生了什么。C++引用实际上是环绕指针的。因此,如果没有引用,代码将如下所示:

    int main() {
        std::string *s1;
        s1 = new std::string("perry");
        std::cout << s1->c_str() << std::endl;
        doMojo( s1 );
        std::cout << s1->c_str() << std::endl; // now pieterson!
    }
    void doMojo( std::string *&str ) {
        str = new std::string("pieterson");
        std::cout << str->c_str() << std::end;
    }
    

    注意无害的符号和:

    void doMojo( std::string *&str ) {
    

    这才是真正的秘密。这一点,以及前面解释的关于Java字符串的不可变性的答案应该使您了解Java和C++引用之间的区别。

    干杯,

    JRH。

        4
  •  0
  •   yyu80    9 年前

    Java中的字符串是不可变的,一旦创建就不能修改。在dohello()中使用赋值实际上创建了一个新的字符串对象,而不是修改现有的字符串对象。结果,2个Java引用(一个在主,另一个在DoHoad)分别向2个不同的字符串引用字符串。这就是为什么你会看到C++和Java之间的不同结果。