简体   繁体   English

STACK.peek函数,遇到麻烦,C ++

[英]STACK.peek function, having some trouble, C++

CARD& STACK::peek()
{
    if(cards.size == 0)
    {
        CARD temp = CARD {-1, -1};
        return temp;
    }
    return cards.back();
}

This is the function I am having trouble with. 这是我遇到的功能。

  • CARD is just a struct with two int variables, called rank and suit . CARD只是具有两个int变量的struct ,称为ranksuit

  • STACK is a class that manages an std::vector<CARD> , that is called cards . STACK是一个class管理的std::vector<CARD>即称为cards

The function is supposed to return a reference to the card on top of the stack, or return the reference to a dummy card if the vector is empty. 该函数应该返回reference到卡上的堆栈的顶部,或者所述参考返回到虚拟卡,如果vector是空的。

First of all, I get a warning that says a reference to a local variable temp is returned. 首先,我得到一条警告,提示返回对局部变量temp的引用。 What is wrong with that? 怎么了 How will that effect the function? 这将如何影响功能? What do I do about it? 我该怎么办?

Second, I am trying to use this function with another function I created called cardToString 其次,我尝试将此函数与我创建的另一个函数cardToString

char* cardToString(CARD& c);

It is supposed to use the rank and suit variables in the passed CARD to look up string values in a table, concatenate the two strings together, and return a pointer to the new string. 应该使用传递的CARDranksuit变量来查找表中的字符串值,将两个字符串连接在一起,并返回指向新字符串的指针。

So the end result looks like: 因此最终结果如下所示:

cout<<cardToString(deck.peek())<<"\n";

but this line of code will execute up to the cardToString function, then just stop for some reason. 但是这一行代码将执行到cardToString函数,然后由于某种原因而停止。 It is annoying the hell out of me because it just stops, there is no error message and there does not look like there is anything wrong to me. 这让我很烦恼,因为它只是停止了,没有错误消息,而且看起来好像没有什么错。

Can somebody help me out? 有人可以帮我吗?

Edit: here is the cardToString function 编辑:这是cardToString函数

char *cardToString(const CARD& c)
{
    if(c.r >= 13 || c.r < 0 || c.s >= 4 || c.s < 0)
    {
        std::cout<<"returned null";
        return NULL;
    }

    char *buffer = new char[32];

    strcpy(buffer, RANKS[c.r]);
    strcat(buffer, " of ");
    return strcat(buffer, SUITS[c.s]);
}

I specifically want the function STACK.peek() to return the address of the CARD that already exists on the top of the STACK . 我特别希望函数STACK.peek()返回STACK顶部已经存在的CARD地址。 It seems to make more sense to do that than to create a copy of the card that I want to return. 这样做似乎比创建我要退还的卡的副本更有意义。

First of all, I get a warning that says a reference to a local variable temp is returned. 首先,我得到一条警告,提示返回对局部变量temp的引用。 What is wrong with that? 怎么了 How will that effect the function? 这将如何影响功能? What do i do about it? 我该怎么办?

A local variable, as it name implies, is local to the function it belongs to, so it's destroyed as the function returns; 顾名思义,局部变量是其所属函数的局部变量,因此在函数返回时会被销毁。 if you try to return a reference to it, you'll return a reference to something that will cease to exist at the very moment the function returns. 如果您尝试返回对它的引用,则将返回对在函数返回的那一刻将不复存在的内容的引用。

Although in some cases this may seem to work anyway, you're just being lucky because the stack hasn't been overwritten, just call some other function and you'll notice it will stop working. 尽管在某些情况下这似乎仍然可以正常工作,但是由于堆栈没有被覆盖,您很幸运,只需调用其他函数,您就会注意到它将停止工作。

You have two choices: first of all, you can return the CARD by value instead of reference; 您有两种选择:首先,您可以按值而不是引用返回CARD this, however, has the drawback of not allowing the caller to use the reference to modify the CARD as is stored in the vector (this may or may not be desirable). 但是,这样做的缺点是不允许调用者使用引用来修改存储在vectorCARD (这可能是希望的,也可能是不希望的)。

Another approach is to have a static dummy CARD instance stored in the STACK class, that won't have these lifetime problems, and that can be returned when you don't have elements in the vector ; 另一种方法是在STACK类中存储一个静态虚拟CARD实例,该实例不会出现这些生存期问题,并且当vector没有元素时可以将其返回; however, you should find a method to "protect" its field, otherwise a "stupid" caller may change the values of your "singleton" dummy element, screwing up the logic of the class. 但是,您应该找到一种“保护”其字段的方法,否则“愚蠢”的调用者可能会更改“单身”虚拟元素的值,从而弄乱了类的逻辑。 A possibility is to change CARD in a class that will encapsulate its fields, and will deny write access to them if it's the dummy element. 一种可能是在将封装其字段的class中更改CARD ,并且如果它是伪元素,则将拒绝对其的写访问。

As for the cardToString function, you're probably doing something wrong with the strings (and I'm almost sure you're trying to return a local also in this case), but without seeing the body of the function it's difficult to tell what. 至于cardToString函数,您可能cardToString字符串做错了(在这种情况下,我几乎可以肯定,您也试图返回本地变量),但是如果看不到函数的主体,很难分辨出什么。

By the way, to avoid many problems with strings I suggest you to use, instead of char * , the std::string class, which takes away most of the ugliness and of the low level memory management of the usual char * . 顺便说一句,以避免而不是用绳子,我建议你使用的很多问题, char * ,该std::string类,这需要最丑陋的和平时的水平低内存管理之外char *

Also, I'd suggest you to change cardToString to take a const reference, because most probably it doesn't need to change the object passed as reference, and it's good practice to clearly mark this fact (the compiler will warn you if you try to change such reference). 另外,我建议您将cardToString更改为const引用,因为很可能不需要更改作为引用传递的对象,并且良好的做法是清楚地标记这一事实(如果尝试,编译器会警告您更改此类参考)。


Edit The cardToString function should be working fine, as long as the RANKS and SUITS arrays are ok. 编辑 cardToString函数应该可以正常工作,只要RANKSSUITS数组正常即可。 But , if you used that function like you wrote, you're leaking memory, since for each call to cardToString you make an allocation with new that is never freed with delete ; 但是 ,如果您像编写时那样使用该函数,则会cardToString内存,因为对于每次对cardToString调用,您都使用new进行分配,而new永远不会通过delete释放。 thus, you are losing 32 bytes of memory per call. 因此,每个调用将丢失32个字节的内存。

As stated before, my tip is to just use std::string and forget about these problems; 如前所述,我的技巧是仅使用std::string并忽略这些问题; your function becomes as simple as this: 您的函数变得像这样简单:

std::string cardToString(const CARD& c)
{
    if(c.r >= 13 || c.r < 0 || c.s >= 4 || c.s < 0)
        return "(invalid card)";

    return std::string(RANKS[c.r]) + " of " + SUITS[c.s];
}

And you don't need to worry about memory leaks and memory allocations anymore. 您无需担心内存泄漏和内存分配。


For the reference/value thing: if the caller do not need to use the reference to modify the object stored in the vector, I strongly suggest passing it by value. 对于引用/值的事情:如果调用者不需要使用引用来修改存储在向量中的对象,则强烈建议按值传递它。 The performance hit is negligible: two int s instead of one pointer means 8 vs 4 bytes on most 32 bit architectures, and 8 bytes vs 8 bytes on most 64 bit machines (and also accessing the fields via pointer has a small cost). 性能下降的影响可以忽略不计:在大多数32位体系结构上,两个int而不是一个指针意味着8个字节对4个字节,而在大多数64位机器上则意味着8个字节对8个字节(而且通过指针访问字段的开销很小)。

This kind of micro-optimization should be the last of your concerns. 这种微优化应该是您最后关心的问题。 Your top priority is to write correct and working code, and the last thing you should do is to let micro-optimization get in the way of this aim. 您的头等大事是编写正确有效的代码,最后要做的就是让微优化妨碍实现此目标。

Then, if you experience performance problems, you'll profile your application to find where the bottlenecks are and optimize those critical points. 然后,如果遇到性能问题,将对应用程序进行概要分析,以找出瓶颈所在,并优化这些关键点。

You cannot return a reference to a local variable, because the local variable no longer exists when the function returns. 您无法返回对局部变量的引用,因为函数返回时该局部变量不再存在。

You need to return by-value, not by-reference (ie CARD STACK::peek() { ... } ). 您需要返回按值而不是按引用(即CARD STACK::peek() { ... } )。

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

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