使用构造函数将数组传递给对象后,值已更改(在 c++ 中)。我想不通为啥

Posted

技术标签:

【中文标题】使用构造函数将数组传递给对象后,值已更改(在 c++ 中)。我想不通为啥【英文标题】:After passing an array to an object using the constructer, the values have been changed (in c++). I can not figured why使用构造函数将数组传递给对象后,值已更改(在 c++ 中)。我想不通为什么 【发布时间】:2016-01-17 10:47:42 【问题描述】:

我学会了如何在函数中传递一个(整数)数组,也知道如何在构造函数中进行。但是当我访问刚刚创建的对象中的数组时,值已经改变了。我几乎尝试了一切。我给新数组一个新名称,尝试使用 this-> 访问值并将数组存储为私有元素,以确保它不能以某种方式更改。我想我错过了一些重要的事情。

我想我不是发送数组,而是发送数组第一个元素的地址。但是,当在我创建数组的位置访问数组时,值是正确的。

最好用我做的例子来说明问题。我只是在初始化“Player Joyce”时将数组“keys”从对象“Game”发送到对象“Player”。我将此数组存储在名称“keyspressed”下。在初始化“Game game”和“Player Joyce”后,我从一个游戏循环中连续访问函数“render()”。我已经在不同的构造函数和函数中打印了数组的值。

简而言之,我希望“keyspressed”的值始终保持 1, 2, 3, 4, 5。

我已经编辑了我的示例并制作了一个 MCVE。我希望现在有人可以更好地帮助我:p

#include<stdio.h>
#include<vector>

class Player 
    private:

    int *keyspressed;

    public:

    Player(int keys[5]) 
        keyspressed = keys;
        printf("%i - %i - %i - %i - %i from when Player is constructed\n", keyspressed[0], keyspressed[1], keyspressed[2], keyspressed[3], keyspressed[4]);
    
    void render() 
        printf("%i - %i - %i - %i - %i from render() in Player\n", keyspressed[0], keyspressed[1], keyspressed[2], keyspressed[3], keyspressed[4]);
    
;
class Game 
    private:

    std::vector<Player> players;

    int keys[5] = 1, 2, 3, 4, 5;

    public:

    Game() 
        players.push_back(Player(keys));        
        printf("%i - %i - %i - %i - %i from when Game is constructed\n", keys[0], keys[1], keys[2], keys[3], keys[4]);                
    
    void render() 
        //Render all players
        for (int j = 0; j < players.size(); j++) 
            players[0].render();
        
        printf("%i - %i - %i - %i - %i from render() in Game\n", keys[0], keys[1], keys[2], keys[3], keys[4]);
       

;
class Window 
    private:

    std::vector<Game> games;

    public:

    Window() 
    
    void loadGame() 
        games.push_back(Game());
    
    void render() 
        //render all games
        for (int i = 0; i < games.size(); i++) 
            games[i].render();
        
    
;

class Program 
    private:
    std::vector<Window> windows;

    public:
    Program() 
        //This program uses 1 window
        Window window;
        windows.push_back(window);

        //load game
        windows[0].loadGame();

        run();
    

    void run() 
        //updates the renderer
        for (int i = 0; i < windows.size(); i++) 
            windows[i].render();
        
    
;


int main( int argc, char* args[]) 

    Program program;

    return 0;
;

输出:

1 - 2 - 3 - 4 - 5 from when Player is constructed
1 - 2 - 3 - 4 - 5 from when Game is constructed
237368672 - 32764 - 3 - 4 - 5 from render() in Player
1 - 2 - 3 - 4 - 5 from render() in Game

【问题讨论】:

你如何使用这些类?您能否尝试创建一个Minimal, Complete, and Verifiable Example 并展示给我们看?另外,an array of arrays is not the same as a pointer to a pointer. keys 是一个错字,但这不是问题所在。我想我可以做一个最小的例子,这将花费一些时间。但我只能理解如何更改私有数组“keyspressed”,因为它是私有的,我在“播放器”中没有任何其他方法 @F.Wessels 悬空指针和越界数组访问会导致各种损坏。 private 仅防止故意修改。 ufo_main = new Texture("images/ufo/ufo.png", renderer, ufo_main_location, red, green, blue); 是可疑的,你将局部变量传递给texture 构造函数,而且Player 在复制时也不会正常运行,你最终会得到多个玩家拥有相同的 ufo_main 指针跨度> 我将示例更改为 MCVE。 【参考方案1】:

可能你最终得到的是悬空指针,虽然我不能肯定地说,因为你没有发布MCVE。

为避免此类问题,请停止使用原始指针。相反,使用具有值语义的容器。例如,您可以改用std::array&lt;int, 5&gt; keyspressed;。您可能还想停止对 statesrenderer 使用原始指针。

【讨论】:

我将示例更改为 MCVE。 @F.Wessels 好的。问题是您正在复制Game 对象,因此您最终会得到Player 具有指向Game 对象中的数组的悬空指针,这些数组现在已被销毁。要解决此问题,请停止使用原始指针。始终使用具有所有权语义的容器和/或智能指针。 那么游戏对象什么时候销毁呢?当我制作游戏对象并将其放入向量中时?我真的看不出来。此外,为什么不使用指针,如果你知道如何使用它们会很好用。因此,例如对于渲染器,每个窗口都有 1 个渲染器,所有子对象都获取渲染器的地址。我不明白为什么这是个问题。它就像一个魅力,当我不再需要它们时,我只需指向 NULL。 @F.Wessels games.push_back(Game()); 创建一个游戏,然后在向量中创建该游戏的副本,然后销毁原始游戏。这会在向量中留下带有悬空指针的副本。不使用原始指针的原因是为了避免产生悬空指针的风险。显然,您当前对指针的使用并不“像魅力一样工作”,因为您遇到了您发布的这些问题。【参考方案2】:

我本来打算回答这个问题,但有人抢了我:p,但是我想建议您完全改变将按键和帧速率发送到播放器类的方式。在我的第一个游戏中,In 也是这样做的(通过函数传递它们)但是它很快就变得非常烦人,因为一个类可以访问某个变量的唯一方法是通过参数,这意味着我很快就会有大量的随机参数在每个函数中,这样他们就可以拥有他们需要的变量。

我建议将 Game 设为静态类,并为其提供一堆 get 函数来获取帧速率和按键等内容,这样您就可以避免在播放器中保留 key[5] 和 State 的副本并将它们从你的函数参数。

【讨论】:

那么你的意思实际上是制作一个大型游戏对象,然后让每个玩家从游戏中的 get 方法中访问所需的变量?或者您会考虑根本不制作 Player 对象吗? 是的,我在我的 android 游戏中设置它的方式是我有一个名为“App”的静态类,它包含一个指向“场景”类的指针向量(它允许不同的场景 - 你改变它们之间使用 App::gotoScene(id))。每个 Scene 类都有一个绘制、更新、构造函数和析构函数以及一些 onTouch、onDrag 等函数。所有这些函数都由包含主循环的 App 类协调并从当前场景调用函数,这样场景就不必担心这些事件是如何被检测到的——这对于跨平台应用程序很有用。 然后每个场景类都包含运行场景所需的数据,因此您的 Player 类将被实例化,例如 SceneGame 类。然后播放器使用 App::getFt() 获取帧时间。如果您想要多个播放器,那么 Player 类是有意义的。

以上是关于使用构造函数将数组传递给对象后,值已更改(在 c++ 中)。我想不通为啥的主要内容,如果未能解决你的问题,请参考以下文章

将参数从php中的数组传递给构造函数[重复]

如何将数组传递给构造函数或类?

NSInvocation 将 C 数组传递给 Objective-C 方法

将数组传递给构造函数会产生大小为 1 的数组? [复制]

为啥不允许将数组按值传递给 C 和 C++ 中的函数?

将数组常量传递给枚举构造函数[重复]