简体   繁体   English

在C ++中实例化的首选方法是什么?

[英]What is the preferred way to instantiate in C++?

I am still new to C++. 我还是C ++的新手。 I have found that you can instantiate an instance in C++ with two different ways: 我发现可以用两种不同的方式在C ++中实例化一个实例:

// First way
Foo foo;
foo.do_something();

// Second way
Baz *baz = new Baz();
baz->do_something();

And with both I don't see big difference and can access the attributes. 而且两者都没有太大的区别,可以访问属性。 Which is the preferred way in C++? C ++中首选的方法是什么? Or if the question is not relevant, when do we use which and what is the difference between the two? 或者,如果这个问题不相关,那么我们什么时候使用哪个,两者之间有什么区别?

Thank you for your help. 谢谢您的帮助。

The question is not relevant: there's no preferred way, those just do different things. 这个问题无关紧要:没有首选的方法,它们只是做不同的事情。

C++ both has value and reference semantics. C ++具有值和引用语义。 When a function asks for a value , it means you'll pass it a copy of your whole object. 当函数要求一个值时 ,这意味着您将向其传递整个对象的副本。 When it asks for a reference (or a pointer), you'll only pass it the memory address of that object. 当它要求引用 (或指针)时,您只会将其传递给该对象的内存地址。 Both semantics are convertible, that is, if you get a value, you can get a reference or a pointer to it and then use it, and when you get a reference you can get its value and use it. 两种语义都是可转换的,也就是说,如果您获得一个值,则可以获取一个引用或指向它的指针,然后使用它;当您获得引用时,可以获取其值并使用它。 Take this example: 举个例子:

void foo(int bar) { bar = 4; }
void foo(int* bar) { *bar = 4; }
void test()
{
    int someNumber = 3;
    foo(someNumber); // calls foo(int)
    std::cout << someNumber << std::endl; 
    // printed 3: someNumber was not modified because of value semantics,
    // as we passed a copy of someNumber to foo, changes were not repercuted
    // to our local version

    foo(&someNumber); // calls foo(int*)
    std::cout << someNumber << std::endl;
    // printed 4: someNumber was modified, because passing a pointer lets people
    // change the pointed value
}

It is a very, very common thing to create a reference to a value (ie get the pointer of a value), because references are very useful, especially for complex types, where passing a reference notably avoids a possibly costly copy operation. 创建对值的引用(即获取值的指针)是非常非常普遍的事情,因为引用非常有用,尤其是对于复杂类型,其中传递引用可以避免昂贵的复制操作。

Now, the instantiation way you'll use depends on what you want to achieve. 现在,您将使用的实例化方法取决于您要实现的目标。 The first way you've shown uses automatic storage; 您显示的第一种方法是使用自动存储; the second uses the heap. 第二个使用堆。

The main difference is that objects on automatic storage are destroyed with the scope in which they existed (a scope being roughly defined as a pair of matching curly braces). 主要区别在于,自动存储中的对象会因其存在的作用域而被破坏(作用域被粗略地定义为一对匹配的花括号)。 This means that you must not ever return a reference to an object allocated on automatic storage from a regular function, because by the time your function returns, the object will have been destroyed and its memory space may be reused for anything at any later point by your program. 这意味着您永远不能从常规函数返回对自动存储中分配的对象的引用,因为到函数返回时,该对象将被销毁,并且其内存空间可在以后的任何时候重用于任何用途。您的程序。 (There are also performance benefits for objects allocated on automatic storage because your OS doesn't have to look up a place where it might put your new object.) (由于自动操作系统不必查找可能放置新对象的位置,因此分配给自动存储的对象也具有性能优势。)

Objects on the heap, on the other hand, continue to exist until they are explicitly deleted by a delete statement. 另一方面,堆上的对象将继续存在,直到被delete语句显式删除为止。 There is an OS- and platform-dependant performance overhead to this, since your OS needs to look up your program's memory to find a large enough unoccupied place to create your object at. 这有一个与操作系统和平台有关的性能开销,因为您的操作系统需要查找程序的内存以找到足够大的空闲空间来创建对象。 Since C++ is not garbage-collected, you must instruct your program when it is the time to delete an object on the heap. 由于C ++是不是垃圾收集, 必须在它删除堆中的对象时指导你的程序。 Failure to do so leads to leaks: objects on the heap that are no longer referenced by any variable, but were not explicitly deleted and therefore will exist until your program exits. 否则会导致泄漏:堆上的对象不再由任何变量引用,而是未被显式删除,因此在程序退出之前将一直存在。

So it's a matter of tradeoff. 因此,这是一个权衡的问题。 Either you accept that your values can't outlive your functions, or you accept that you must explicitly delete it yourself at some point. 您要么接受值不能超过函数的寿命,要么接受必须在某个时候明确deletedelete Other than that, both ways of allocating objects are valid and work as expected. 除此之外,两种分配对象的方法都有效并且可以按预期工作。

For further reference, automatic storage means that the object is allocated wherever its parent scope was. 供进一步参考,自动存储意味着将对象分配到其父作用域所在的任何位置。 For instance, if you have a class Foo that contains a std::string , the std::string will exist wherever you allocate your Foo object. 例如,如果您有一个包含std::string Foo类,则无论您分配Foo对象在哪里, std::string都将存在。

class Foo
{
public:
    // in this context, automatic storage refers to wherever Foo will be allocated
    std::string a;
};

int foo()
{
    // in this context, automatic storage refers to your program's stack
    Foo bar; // 'bar' is on the stack, so 'a' is on the stack
    Foo* baz = new Foo; // 'baz' is on the heap, so 'a' is on the heap too
    // but still, in both cases 'a' will be deleted once the holding object
    // is destroyed
}

As stated above, you cannot directly leak objects that reside on automatic storage, but you cannot use them once the scope in which they were created is destroyed. 如上所述,您不能直接泄漏驻留在自动存储中的对象,但是一旦破坏了它们的创建范围,就无法使用它们。 For instance: 例如:

int* foo()
{
    int a; // cannot be leaked: automatically managed by the function scope
    return &a; // BAD: a doesn't exist anymore
}

int* foo()
{
    int* a = new int; // can be leaked
    return a; // NOT AS BAD: now the pointer points to somewhere valid,
              // but you eventually need to call `delete a` to release the memory
}

The first way -- "allocating on the stack" -- is generally faster and preferred much of the time. 第一种方法-“在堆栈上分配”-通常更快,并且在很多时候都是首选。 The constructed object is destroyed when the function returns. 函数返回时,构造的对象将被销毁。 This is both a blessing -- no memory leaks! 这都是福气-没有内存泄漏! -- and a curse, because you can't create an object that lives for a longer time. -还有一个诅咒,因为您无法创建寿命更长的对象。

The second way -- "allocating on the heap" is slower, and you have to manually delete the objects at some point. 第二种方式-“在堆上分配”的速度较慢,您必须在某个时候手动删除对象。 But it has the advantage that the objects can live on until you delete them. 但是这样做的好处是,对象可以一直存在,直到删除它们为止。

The first way allocates the object on the stack (though the class itself may have heap-allocated members). 第一种方法在堆栈上分配对象(尽管类本身可能具有堆分配的成员)。 The second way allocates the object on the heap, and must be explicitly delete 'd later. 第二种方法在堆上分配对象,并且必须在以后显式delete

It's not like in languages like Java or C# where objects are always heap-allocated. 这与Java或C#这样的语言中的对象总是堆分配不同。

They do very different things. 他们做的事情截然不同。 The first one allocates an object on the stack, the 2nd on the heap. 第一个在堆栈上分配一个对象,第二个在堆上分配一个对象。 The stack allocation only lasts for the lifetime of the declaring method; 堆栈分配仅在声明方法的生命周期内持续; the heap allocation lasts until you delete the object. 堆分配将持续到删除对象为止。

The second way is the only way to dynamically allocate objects, but comes with the added complexity that you must remember to return that memory to the operating system (via delete/delete[]) when you are done with it. 第二种方法是动态分配对象的唯一方法,但是它带来了额外的复杂性,您必须记住,完成处理后,必须将该内存返回给操作系统(通过delete / delete [])。

The first way will create the object on the stack, and the object will go away when you return from the function it was created in. 第一种方法将在堆栈上创建对象,当您从创建该对象的函数返回时,该对象将消失。

The second way will create the object on the heap, and the object will stick around until you call delete foo; 第二种方法将在堆上创建对象,并且该对象将一直存在,直到您调用delete foo;为止delete foo; .

If the object is just a temporary variable, the first way is better. 如果对象只是一个临时变量,则第一种方法更好。 If it's more permanent data, the second way is better - just remember to call delete when you're finally done with it so you don't build up cruft on your heap. 如果它是永久性数据,那么第二种方法更好-记住在完成处理后再调用delete ,这样就不会在堆上堆积残骸。

Hope this helps! 希望这可以帮助!

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

相关问题 在C ++中重写运算符的首选方法是什么 - What is the preferred way to override operators in C++ 在c ++中存储一个对象或不存储任何对象的首选方法是什么? - What is the preferred way to store one or no object in c++? 在C ++中将内置类型(int)转换为bool的首选方法是什么? - What is the preferred way in C++ for converting a builtin type (int) to bool? 在C ++中使用auto声明lambda变量的首选方法是什么? - What is the preferred way to use auto to declare a lambda variable in C++? 在C ++中将数据结构表示为字符串的首选方法是什么? - What is the preferred way to represent data structures as strings in C++? 分配C ++类成员数据的首选方法是什么? - What is the preferred way of allocating C++ class member data? 在C ++中包含错误消息的首选方法是什么? - What is the preferred way to include error messages in C++? 在 C++ 中将字符串写入文件的首选方法是什么,使用“+”或多个“<<”? - What is the preferred way to write string to file in C++, use '+' or several '<<'? 在cmake c ++项目中包含库的首选方法是什么? - What's the preferred way to include a library in a cmake c++ project? 在C ++中实现工厂方法的首选方法是什么? - What is the preferred way to implement a factory method in C++?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM