C++ 如何正确地将精灵传递给std::Vector而不破坏其纹理?

C++ 如何正确地将精灵传递给std::Vector而不破坏其纹理?,c++,vector,textures,sprite,sfml,C++,Vector,Textures,Sprite,Sfml,从官方SFML教程中,白盒问题:- “当您设置精灵的纹理时,它在内部所做的只是存储一个指向纹理实例的指针。因此,如果纹理被破坏或移动到内存中的其他位置,精灵最终会得到一个无效的纹理指针。”因此,将看到一个没有纹理的精灵 我有一门课叫世界。在这个类中,我制作了一个名为level的二维整数数组和一个名为blocks的Block类型向量。现在我想在level[I][j]=1时将“Block”对象存储在向量中 “世界”类的头文件:- \ifndef WORLD\u H #定义世界 #包括 #包括“Blo

从官方SFML教程中,白盒问题:-

“当您设置精灵的纹理时,它在内部所做的只是存储一个指向纹理实例的指针。因此,如果纹理被破坏或移动到内存中的其他位置,精灵最终会得到一个无效的纹理指针。”因此,将看到一个没有纹理的精灵

我有一门课叫世界。在这个类中,我制作了一个名为level的二维整数数组和一个名为blocks的Block类型向量。现在我想在level[I][j]=1时将“Block”对象存储在向量中

“世界”类的头文件:-

\ifndef WORLD\u H
#定义世界
#包括
#包括“Block.h”
#包括“Grass.h”
#包括
使用名称空间std;
阶级世界
{
公众:
世界();
虚线绘制(sf::RenderWindow*窗口);
向量块;
私人:
国际水平[12][16];
int-wd;
int hi;
};
#endif//WORLD\u H
“世界”级的cpp文件:-

#包括“World.h”
#包括“Grass.h”
#包括“Block.h”
#包括
#包括
使用名称空间std;
世界::世界():级别{
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1},
{1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
}
{
wd=16;
hi=12;
整数计数=1;
//制作一个“块”对象,并在级别[i][j]=1时在向量中传递它。

对于(int i=0;i您应该自定义块的复制构造,以便它更新纹理指针,例如:

Block::Block(const Block& other)
  : blockT(other.blockT), block(other.block)
{
    block.setTexture(blockT);
}
向量中的
push_back()
强制调整大小,并且新分配的较大缓冲区的元素是从旧元素复制构建的,然后旧元素被“销毁”和解除分配时,将使用该方法

最好支持相同类型的赋值更新,即
操作符=(const Block&rhs)


关于你的“这样就可以看到一个没有纹理的精灵。”-行为更可能是未定义的,因为您正在有效地跟踪一个指向已释放内存的指针,该内存可能随时被新内容损坏,并且在您的测试中碰巧表现为当前缺少纹理,但在一些较小的代码更改后,可能会在其他优化级别崩溃和烧坏nges,在另一个编译器或操作系统等上。

您使用块类存储其自身的sf::Texture实例的解决方案将导致您在内存中挂起纹理的副本。当您按照答案处理块对象时,还需要学习并遵循三的规则

更简单的解决方案是有一个单独的文件名到sf::Textures的std::map,您可以将需要的纹理加载到其中一次,然后在需要的任何地方检索它们

// Have one of these, maybe as a member of your World class?
std::map<std::string,sf::Texture> textures;

// load your textures into it ...
//作为您的世界级会员,是否拥有其中一个?
贴图纹理;
//加载你的纹理到它。。。
然后在你的街区课上

class Block
{
public:
    // constructor now takes a reference to a texture map ...
    Block(float x, float y,std::map<std::string,sf::Texture>& textures);
类块
{
公众:
//构造函数现在引用纹理贴图。。。
块(浮动x、浮动y、标准::贴图和纹理);

在实现中,您可以通过文件名检索所需的纹理,并使用setTexture将其分配给sprite。

在使用名称空间时应更加小心,尤其是在头文件中!:)请参见
#include "Block.h"
#include <iostream>
#include <SFML/Graphics.hpp>

using namespace std;

Block::Block(float px, float py)
{
    if(!(blockT.loadFromFile("textures/block.png")))
    {
        cout<<"Could not load block texture."<<endl;
    }
    block.setTexture(blockT);
    block.setPosition(sf::Vector2f(px, py));
    cout<<px<<endl;
    cout<<py<<endl;
}

void Block::draw(sf::RenderWindow *window)
{
    window->draw(block);
}
Block::Block(const Block& other)
  : blockT(other.blockT), block(other.block)
{
    block.setTexture(blockT);
}
// Have one of these, maybe as a member of your World class?
std::map<std::string,sf::Texture> textures;

// load your textures into it ...
class Block
{
public:
    // constructor now takes a reference to a texture map ...
    Block(float x, float y,std::map<std::string,sf::Texture>& textures);