c++ - STACK.peek 函数,遇到一些问题,C++

标签 c++ class function struct tostring

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

这是我遇到问题的功能。

  • CARD只是一个struct有两个int变量,称为 ranksuit .

  • STACKclass管理 std::vector<CARD> , 即称为 cards .

该函数应该返回一个 reference到堆栈顶部的卡片,或者如果 vector 返回对虚拟卡片的引用是空的。

首先,我收到一条警告,指出对局部变量的引用 temp被退回。这有什么问题?这将如何影响功能?我该怎么办?

其次,我尝试将此函数与我创建的另一个函数 cardToString 结合使用

char* cardToString(CARD& c);

它应该使用 ranksuit传递的变量 CARD在表中查找字符串值,将两个字符串连接在一起,并返回指向新字符串的指针。

所以最终结果是这样的:

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

但这行代码将执行到 cardToString功能,然后由于某种原因停止。这让我很恼火,因为它只是停止,没有错误消息,而且看起来对我来说没有任何问题。

有人可以帮帮我吗?

编辑:这里是 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]);
}

我特别想要函数 STACK.peek()返回 CARD 的地址已经存在于 STACK 的顶部.这样做似乎比创建我要退回的卡片的拷贝更有意义。

最佳答案

First of all, I get a warning that says a reference to a local variable temp is returned. What is wrong with that? How will that effect the function? What do i do about it?

顾名思义,局部变量是它所属函数的局部变量,因此在函数返回时被销毁;如果您尝试返回对它的引用,您将返回对在函数返回的那一刻将不复存在的东西的引用。

虽然在某些情况下这似乎仍然有效,但你只是幸运,因为堆栈没有被覆盖,只要调用一些其他函数,你就会发现它会停止工作。

您有两个选择:首先,您可以通过值而不是引用返回CARD;然而,这样做的缺点是不允许调用者使用引用来修改存储在 vector 中的 CARD(这可能是理想的,也可能不是理想的)。

另一种方法是在 STACK 类中存储一个静态虚拟 CARD 实例,它不会有这些生命周期问题,并且可以在您不这样做时返回'在 vector 中有元素;但是,您应该找到一种方法来“保护”它的字段,否则“愚蠢”的调用者可能会更改您的“单例”虚拟元素的值,从而搞砸类的逻辑。一种可能性是更改 class 中的 CARD,它将封装其字段,如果它是虚拟元素,将拒绝对它们的写访问。

至于 cardToString 函数,您可能对字符串做错了什么(而且我几乎可以肯定在这种情况下您也试图返回本地),但没有看到很难说出函数的主体是什么。

顺便说一句,为了避免字符串的许多问题,我建议您使用 std::string 类代替 char *,它消除了大部分通常的 char * 的丑陋和低级内存管理。

此外,我建议您更改 cardToString 以采用 const 引用,因为它很可能不需要更改作为引用传递的对象,并且清楚地标记这一事实是很好的做法(如果您尝试更改此类引用,编译器会警告您)。


编辑 cardToString 函数应该可以正常工作,只要 RANKSSUITS 数组正常。 但是,如果你像你写的那样使用那个函数,你就会泄漏内存,因为每次调用 cardToString 你都会用 new 进行分配永远不会用 delete 释放;因此,每次调用都会丢失 32 字节的内存。

如前所述,我的建议是只使用 std::string 并忘记这些问题;你的功能变得如此简单:

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];
}

而且您无需再担心内存泄漏和内存分配问题。


对于引用/值的事情:如果调用者不需要使用引用来修改存储在 vector 中的对象,我强烈建议按值传递它。性能损失可以忽略不计:两个 int 而不是一个指针意味着在大多数 32 位架构上是 8 字节对 4 字节,在大多数 64 位机器上是 8 字节对 8 字节(并且还通过指针访问字段成本很小)。

这种微优化应该是您最后关心的问题。您的首要任务是编写正确的有效的代码,您最不应该做的就是让微优化妨碍这一目标。

然后,如果您遇到性能问题,您将分析您的应用程序以找出瓶颈所在并优化这些关键点。

关于c++ - STACK.peek 函数,遇到一些问题,C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5559970/

相关文章:

内部类的 C++ vector

python - 难以理解函数的工作原理

javascript - 创建 JavaScript 函数来更改先前声明的变量

javascript - 为什么从构造函数返回时未定义原型(prototype)?

c# - 二进制搜索算法的扩展,用于查找要在数组中搜索的键值的第一个和最后一个索引

c# - 当我的应用程序没有响应时使用 c# 终止我的应用程序

c++ - 将剪切、复制、粘贴快捷方式更改为 Qt 5 中的自定义插槽

c++ - 有没有办法避免 cpp 文件中所有方法的重复类实例化?

C# .net 对象引用未设置为静态类上的对象实例

javascript - ECMAScript 2015(ECMAScript 6) 有类初始值设定项吗?