访问数组中的对象重新创建对象?

Posted

技术标签:

【中文标题】访问数组中的对象重新创建对象?【英文标题】:Accessing object in array recreating object? 【发布时间】:2015-06-30 05:54:54 【问题描述】:

我正在制作一个主机游戏,我正在制作一张地图。地图是一个向量数组。向量包含我打印到控制台的字符。我的代码:

“窗口.h”

#include <string>
#include <vector>

class Row 
public:
    std::vector<char> row;
    int id;
    Row();
    void printRow();
    void resetRow();
    void insertStringIntoRow(std::string toInsert, int startIndex);
    std::vector<char> getRow() 
        return row;
    
;

class Window 
public:
    void showMap();
    void writeToMap(std::string stringToInsert, int rowNum, int startIndex);
    void writeInRectangle(std::string stringToWrite, int rowNum, int startIndex);
    void setCursorToPosition(int x, int y);
    void resetMap();
    Row getRowAt(int index);
;

void initColors();
void setWindow(Window windowToSet);
Window getGameWindow();

“窗口.cpp”

#include "Window.h"
#include <iostream>
#include <Windows.h>
#include <WinBase.h>
#include <stdlib.h>
#include "color.h"

using namespace eku;

Row map[25];

//Class Window
void Window::showMap() 
    setCursorToPosition(0, 0);
    for (int i = 0; i < 25; i++) 
        getRowAt(i).printRow();
    


void Window::writeToMap(std::string stringToInsert, int rowNum, int startIndex) 
    Row r = getRowAt(rowNum);
    r.insertStringIntoRow(stringToInsert, startIndex);


void Window::writeInRectangle(std::string stringToWrite, int rowNum, int startIndex) 
    if (startIndex != 0) 
        std::string topbar = "~";
        for (int i = 0; i < stringToWrite.length() + 2; i++) 
            topbar += ' ';
        
        topbar += '^';
        getRowAt(rowNum - 1).insertStringIntoRow(topbar, startIndex - 1);
    

    std::string toInsert = "~ ^" + stringToWrite + "~ ^";
    getRowAt(rowNum).insertStringIntoRow(toInsert, startIndex - 1);

    if (startIndex != 25) 
        std::string bottombar = "~";
        for (int i = 0; i < stringToWrite.length() + 2; i++) 
            bottombar += ' ';
        
        bottombar += '^';
        getRowAt(rowNum + 1).insertStringIntoRow(bottombar, startIndex - 1);
    


void Window::setCursorToPosition(int x, int y) 
    HANDLE hOut;
    COORD Position;
    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    Position.X = x;
    Position.Y = y;

    SetConsoleCursorPosition(hOut, Position);


void Window::resetMap() 
    for (Row row : map) 
        row.resetRow();
    


Row Window::getRowAt(int index)

    return map[index];


//Class Row
const char WHITEBACKCOL = '~';
const char DEFCOL = '^';

int i = 0;

Row::Row() 
    row.resize(80, ' ');
    id = i;
    i++;


void Row::printRow() 
    for (int i = 0; i < row.size(); i++) 
        switch (row[i]) 
        case WHITEBACKCOL:
            setcolor(black, white);
        case DEFCOL:
            setcolor(white, black);
        default:
            std::cout << row[i];
        
    


void Row::resetRow() 
    row.resize(80);
    for (int i = 0; i < 80; i++) 
        row[i] = ' ';
    


void Row::insertStringIntoRow(std::string toInsert, int startIndex) 
    int endIndex = (startIndex + toInsert.length());
    int stringPos = 0;
    for (int i = startIndex; i < endIndex; i++) 
        if (i < row.size() - 1) 
            row.at(i) = toInsert[stringPos];
        
        else 
            row.push_back(toInsert[stringPos]);
        
        stringPos++;
    

Window defWindow;

void initColors() 
    concolinit();
    setcolor(white, black);


void setWindow(Window windowToSet) 
    defWindow = windowToSet;


Window getGameWindow() 
    return defWindow;

“Main.cpp”

#include <iostream>
#include "GameEngine.h"
#include "Window.h"

int main() 
    setWindow(Window());
    initColors();

    getGameWindow().writeInRectangle("Hia", 1, 10);

    getGameWindow().showMap();

每当我调用showMap() 时,我得到的只是一个空白控制台。它似乎只打印默认的空格映射,而不是我输入的文本。我还尝试仅使用 printRow() 打印我编辑的单行,但它们也只显示空格。 我能够在insertStringIntoRow() 方法中查看对向量行的更改,但是即使更改应该在那里,它们也没有显示在其他任何地方。几乎每次我访问它时都会创建我的Row 对象。我是 C++ 新手,因此不胜感激。提前致谢!

【问题讨论】:

您的输出是空格还是 WHITEBACKCOL 或 DEFCOL 。 是的,在 writeToMap 中创建的行是被丢弃的临时行。 【参考方案1】:

此功能使用不正确。警告标志是它是非常量的,但用作访问器。它返回向量的副本,而不是引用。

std::vector<char> getRow() 
    return row;

按照您的调用方式,您希望它就地修改行,但您实际上所做的只是修改行的副本,然后立即丢弃该副本。示例:

getRowAt(rowNum).insertStringIntoRow(toInsert, startIndex - 1);

解决此问题的简单方法是返回来自getRow() 的引用:

std::vector<char> & getRow() 
    return row;

要解决的另一件事是将其分配给临时变量而不是内联使用它。在这种情况下,您可以将临时作为参考:

Row & r = getRowAt(rowNum);
r.insertStringIntoRow(stringToInsert, startIndex);

实现这一点的正确方法是提供一个常量版本,这样它仍然可以在调用者不想修改的常量对象上调用它。

const std::vector<char> & getRow() const 
    return row;

我只在此处添加了这个额外的部分,因为这是一种很好的做法,但您不应该在这个程序中这样做。它会使您的代码变得混乱,这些代码已经充满了更糟糕的做法 =)

【讨论】:

成功了!谢谢。我来自 Java,所以这个概念对我来说是新概念。【参考方案2】:

发送对 writeToMap() 的引用而不是变量。 这将更改原始地图对象而不是复制变量。

【讨论】:

以上是关于访问数组中的对象重新创建对象?的主要内容,如果未能解决你的问题,请参考以下文章

深入理解Java虚拟机——对象创建与访问指令

Jvm(46),指令集----对象创建与访问指令

使用 ASM 监视 Java 中的对象创建时出现“VerifyError:期望在堆栈上找到对象/数组”?

创建对象的过程及对象的访问定位

使用指针访问数组中的对象数据成员

vue 改变数组中对象的属性怎么重新渲染列表