c++ - Rust与C++ : Returning objects from functions

标签 c++ rust

我是Rust的新手,试图了解从函数返回对象时如何传递所有权。
在以下基于引用的实现中,由于引用不具有所有权,因此当“s”超出范围时,它将被丢弃并被释放。

fn dangle() -> &String { // dangle returns a reference to a String

    let s = String::from("hello"); // s is a new String

    &s // we return a reference to the String, s
} // Here, s goes out of scope, and is dropped. Its memory goes away.
  // Danger!
通过不返回引用来解决此问题:
fn no_dangle() -> String {
    let s = String::from("hello");

    s
}
现在,我试图通过C++实现来理解这一点,如下所示:
std::string no_dangle() {
    std::string s("hello world");
    return s;
}
根据我的理解,在C++中,当从函数返回“s”时,使用复制构造函数创建了另一个拷贝,并且在函数内部创建的“s”被释放了。这意味着,创建了两个对象,它们实际上并不是光学对象。内存的条件。
我的问题:
  • 在Rust中,当从函数返回“s”时,不创建任何其他对象。仅返回所有权。堆中分配的原始对象保持不变。这是正确的吗?
  • 在C++中,您可以通过返回对象和指针(智能指针或原始指针)从函数中返回“事物”。但是在Rust中,唯一返回“事物”的方法如上所述,与C++相比,它几乎返回了一个“事物”。智能指针?
  • 最佳答案

    rust和C++都是值类型的语言,因此除非明确要求,否则不会在堆上分配对象/结构。因此,在两种情况下都不会在堆上分配有问题的字符串对象/结构。在这两种语言中,字符串都使用动态分配的后备缓冲区,该缓冲区存储在堆中,但这是一个重要的区别。
    因此,在rust中,如果按值返回,则对象将被移动,该对象始终等效于平直的memcpy,因为rust结构不允许具有自定义移动逻辑,并且克隆必须是显式的。该内存复制将指针复制到后备存储器,以便字符串对象可以位于不同的内存中,但后备缓冲区保持不变。
    在C++中,对象可以具有非平凡的拷贝,并且(在C++ 11及更高版本中)可以移动构造函数。因此,如果除了返回命名值以外,还必须调用copy或move构造函数。但是,对于从函数返回的特定情况,复制省略规则起作用。这表示可以选择(在C++ 17及更高版本中,某些简单情况下是必需的),如果对象是在return语句中初始化的,或者来自具有自动存储持续时间的位置,则编译器不会调用copy/move构造函数,但是在最初创建返回对象时,该对象直接构造到调用者提供的存储中,这意味着在返回时不需要复制或移动。这就是所谓的返回值优化。
    如果在C++ 11或更高版本中,您要返回的值不是对象初始化的值,也不是具有自动存储持续时间的命名值(或者在这种情况下,由编译器自行决定,但C++ 17和更高版本中的对象初始化除外),例如作为调用另一个函数的结果,将调用move构造函数,在这种情况下,只需将指针复制到后备存储并清除旧字符串中的指针即可。在这种情况下,其行为就像使用rust 。如果该类型具有更复杂的move构造函数,则由于该移动它可以做任何事情。
    最后,在C++ 98中,如果要返回的值不是对象初始化值或具有自动存储持续时间的命名值,则将调用复制构造函数,将后备存储复制到新的后备存储,然后将该后备存储回来。导致指向不同内存的新字符串。然后,作用域结束时,析构函数将释放旧的内存。
    另外,C++实现可以使用小字符串优化,其中将小字符串直接存储在字符串对象中。在这种情况下,将没有后备存储,并且即使对象已移动,也必须将字符串复制。
    最后要注意的一点是,在C++ 11之前,std::string实现通常使用引用计数的后备存储。在这种情况下,拷贝将增加后备存储上的引用计数,而析构函数将减少其增量,但不会取消分配,因为仍然存在对该存储的引用。在这种情况下,生成的字符串仍将指向原始的后备存储,但是所花费的过程要比迁移的过程稍微昂贵。随着move构造函数的引入,这种情况已变得不那么普遍了。
    为了快速回答第二个问题,rust还允许返回智能指针,指针和引用,但是rust借用检查器将阻止返回对对象本地对象的引用,因为它们将没有足够的生存期。这不会阻止返回对参数和全局变量(例如字符串文字或线程本地变量)的引用,因为它们的生命周期比函数长。

    关于c++ - Rust与C++ : Returning objects from functions,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62980187/

    相关文章:

    c++ - 传递外围对象以用作嵌入式系统中的类成员

    C++ : Restricting object instantiation with friend classes

    struct - 如何从不同的模块实例化一个公共(public)元组结构(带有私有(private)字段)?

    rust - 借用检查器检查可变引用的最佳实践是什么?

    macos - Rust cargo dylib 说明

    c++ - 如何为 C++ (MSVC 2008) 解决方案创建语言附属 DLL?

    c++ - 访问 float 的 4 个字节是否会破坏 C++ 别名规则

    c++ - 我无法编译此 dijkstra 代码。 (算法设计手册)

    rust - 由于类型不匹配,对 Vec<Result<T, E>> 进行分区失败

    rust - 如何从Reverse()中获取值?