简体   繁体   English

什么是安全的? 从函数返回结构或指针

[英]What is safe? returning a structure or the pointer from a function

#include <iostream>

struct person_t{
        int age;
};

person_t get_person1(){
        person_t person;
        person.age = 10;
        return person;
}

person_t * get_person2(){
        person_t *person = new person_t;
        person->age = 20;
        return person;
}

int main(){
        person_t person1 = get_person1();
        person_t *person2 = get_person2();
        std::cout << person1.age << std::endl;
        std::cout << person2->age << std::endl;
        delete person2;
        return 0;
}

I want to know what is the safest way to return a structure from a function. 我想知道从函数返回结构的最安全的方法是什么。

As in the answers to the questions in here and here , it is said that when you create a object as in get_person1() , that object will be destroyed after when it goes out of scope. 正如在这里这里的问题的答案中所说,当你在get_person1()创建一个对象时,该对象将在它超出范围之后被销毁。

But when I search for "How to return a struct from function c++", it suggest me method one (with get_person1() ) (Example here ). 但是当我搜索“如何从函数c ++返回结构”时,它建议我使用方法一(使用get_person1() )( 此处为示例)。 But I think that method will destroy the object after the function was called and I think method 2 is the safest. 但我认为该方法会在调用函数后销毁对象,我认为方法2是最安全的。

Am I wrong here..? 我错了吗? Or any opinion regarding this topic..? 或者关于这个话题的任何意见..?

Thank you!! 谢谢!!

Use return by value for 3 reasons: 使用按值返回有三个原因:

  • It makes your code readable 它使您的代码可读
  • Your struct here is small (one int) so it is like returning an int. 你的结构在这里很小(一个int)所以它就像返回一个int。 You can do that in C++, it is efficient 你可以用C ++做到这一点,效率很高
  • In C++17 (and most compiler before that) the cost of the intermediate copy of the object will be avoided. 在C ++ 17(以及之前的大多数编译器)中,将避免对象的中间副本的成本。 It is known as RVO. 它被称为RVO。 You need to put only one return in your get_person function. 你需要在get_person函数中只输入一个返回值。

it is said that when you create a object as in get_person1() , that object will be destroyed after when it goes out of scope. 据说当你在get_person1()创建一个对象时,该对象在超出范围之后将被销毁。

What is destroyed is the local object (ie: person inside get_persion1() ). 被破坏的是本地对象(即: get_persion1()内部的person )。 What is returned is a copy of that object: a struct person_t is copied (it may be moved as well). 返回的是该对象的副本 :复制struct person_t (也可以移动它)。 So, it is safe. 所以,这是安全的。


get_person2() is also safe, but consider using smart pointers instead of raw pointers : get_person2()也是安全的,但考虑使用智能指针而不是原始指针

std::unique_ptr<person_t> get_person2(){
        auto person = std::make_unique<person_t>();
        // For pre-C++14
        // std::unique_ptr<person_t> person(new person_t);
        person->age = 20;
        return person;
}

That way, the caller to get_person2() doesn't have to call delete (it may forget to do so). 这样, get_person2()的调用者不必调用delete (它可能忘记这样做)。

Both approaches are equally safe - neither one causes undefined behavior, and the value set inside the function makes it back to the caller. 这两种方法都同样安全 - 两者都不会导致未定义的行为,并且函数内部设置的值会使其返回给调用者。

The main difference is that the first approach copies the struct , while the second approach copies a pointer to struct . 主要区别在于第一种方法复制struct ,而第二种方法复制指向struct的指针。 When the struct is tiny, such as in your example, there is no difference. struct很小时,例如在你的例子中,没有区别。 When the struct becomes large, returning a pointer may save you some CPU cycles at the expense of additional memory allocation, so it is far from being a guaranteed win. struct变大时,返回指针可能会以额外的内存分配为代价来节省一些CPU周期,因此它远远不能保证获胜。

Obviously, the second approach has another drawback in that one has to delete the struct eventually. 显然,第二种方法的另一个缺点是必须最终delete struct The first approach is free from this requirement. 第一种方法不受此要求的限制。

Both methods are safe. 这两种方法都很安全。

Method 1 is safe since the local person is copied out from the function scope. 方法1是安全的,因为本地person被从功能范围中复制出来。 Oftentimes, Return Value Optimization (RVO) can be used to avoid copying. 通常, 返回值优化(RVO)可用于避免复制。

Method 2 is also safe since memory for an instance of person is allocated in the heap. 方法2也是安全的,因为person的实例的内存在堆中分配。 This allocation is obviously valid outside the scope of the function. 这种分配显然在函数范围之外有效。 However, you must remember to deallocate said memory when you are done using it. 但是,您必须记住在完成使用后释放所述内存。 This is not critical in your example code. 这在您的示例代码中并不重要。 Heap-allocations are automatically deallocated when main terminates , so for your short example you do not actually "need" delete person2 . 当主要终止时堆分配会自动解除分配 ,因此对于您的简短示例,您实际上并不“需要” delete person2

Your question is which of said methods are "safest". 你的问题是哪种方法是“最安全的”。 This is not possible to answer objectively, although I would argue that a wide majority of C++ programmers would advise against method 2 in favor of method 1. Many C++ programmers would recommend using smart-pointers. 虽然我认为绝大多数C ++程序员会建议方法2支持方法1,但这是不可能客观回答的。许多C ++程序员会建议使用智能指针。

Final remark: Method 1 and method 2 are fundamentally different. 最后评论:方法1和方法2根本不同。 Allocating memory on the stack (method 1) versus allocating memory on the heap (method 2) are two different concepts. 在堆栈上分配内存(方法1)与在堆上分配内存(方法2)是两个不同的概念。 There are many more considerations to make but "safety" considerations . 还有许多考虑因素需要考虑“安全性”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM