C++ 字符串和商店
在下面的程序中,一个字符串被添加到一个空存储中。然后,该存储元素的地址存储在指针“s1”中。然后添加另一个字符串,这会以某种方式导致指向原始元素的指针失败C++ 字符串和商店,c++,pointers,set,elements,stdvector,C++,Pointers,Set,Elements,Stdvector,在下面的程序中,一个字符串被添加到一个空存储中。然后,该存储元素的地址存储在指针“s1”中。然后添加另一个字符串,这会以某种方式导致指向原始元素的指针失败 #include <iostream> #include <string> #include <vector> class store2 { public: void add(std::string s) {words.push_back(s); last_added2 = &am
#include <iostream>
#include <string>
#include <vector>
class store2
{
public:
void add(std::string s) {words.push_back(s); last_added2 = &words.at(words.size() - 1);}
std::string* last_added() {return last_added2;}
private:
std::string* last_added2;
std::vector<std::string> words;
};
void main()
{
store2 store;
store.add("one");
std::string* s1 = store.last_added();
std::cout<<*s1<<std::endl;
store.add("two");
std::cout<<*s1<<std::endl; // crash
}
#包括
#包括
#包括
二级仓库
{
公众:
void add(std::string s){words.push_back(s);last_added2=&words.at(words.size()-1);}
std::string*last_added(){return last_added2;}
私人:
std::string*最后添加的2;
向量词;
};
void main()
{
商店2;
储存。添加(“一”);
std::string*s1=store.last_added();
std::cout当您向std::vector
添加新项时,该向量可能需要扩展其缓冲区,这样做可能会将缓冲区移动到不同的内存区域。因此,指向其元素的指针将无效。简而言之,在调整向量大小后,指向向量项的指针不保证有效如果向量没有足够的保留空间,dpush_back
可能会调整向量大小
您可以在开始时为向量保留空间,但之后可以分配到向量中的项数会受到限制。如果需要确保集合中的指针保持有效,您可能需要向量以外的其他对象(例如,您可以使用std::deque
或std::list
——通常两者之间首选std::deque
)
或者,您可以返回字符串的索引,并提供一个成员函数,在使用向量时将其索引到向量中,而不是返回指针(通常是一个糟糕的主意)。修改向量的内容时,向量的迭代器可能会失效。请参阅
如果确实希望保留现有接口并保留插入向量的元素的指针,则可以按指针而不是按值存储字符串,例如:
#include <iostream>
#include <string>
#include <vector>
#include <memory>
class store2
{
public:
store2 ()
{
}
~store2 ()
{
for (std::vector<std::string *>::iterator it =
words.begin (), end_it = words.end ();
it != end_it; ++it)
{
delete *it;
}
words.clear ();
}
void add (const std::string & s)
{
std::auto_ptr<std::string> v (new std::string (s));
words.push_back (v.get ());
v.release ();
}
std::string *last_added ()
{
return words.back ();
}
const std::string *last_added () const
{
return words.back ();
}
private:
std::vector<std::string *> words;
};
int main ()
{
store2 store;
store.add("one");
std::string* s1 = store.last_added();
std::cout<<*s1<<std::endl;
store.add("two");
std::cout<<*s1<<std::endl; // no crash :-)
}
#包括
#包括
#包括
#包括
二级仓库
{
公众:
仓库2()
{
}
~2()
{
for(std::vector::iterator)=
words.begin(),end_it=words.end();
它!=结束它;++它)
{
删除*它;
}
words.clear();
}
void add(const std::string&s)
{
std::auto_ptr v(新的std::字符串);
推回(v.get());
v、 释放();
}
std::string*上次添加()
{
返回words.back();
}
const std::string*最后添加()const
{
返回words.back();
}
私人:
向量词;
};
int main()
{
商店2;
储存。添加(“一”);
std::string*s1=store.last_added();
std::cout您有什么特别的原因想使用指针(heap)吗?
如果没有,就做:
class store2
{
public:
void add(std::string s) {words.push_back(s);}
std::string last_added() { if (words.size() == 0) return "";
return words[words.size()-1];}
private:
std::vector<std::string> words;
}
类存储2
{
公众:
void add(std::string s){words.push_back(s);}
std::string last_added(){if(words.size()==0)返回“”;
返回单词[words.size()-1];}
私人:
向量词;
}
;它不需要是std::vector,许多std::vector功能都不是必需的,但它确实需要调整大小,元素确实需要可靠的寻址。如果不需要随机访问,可以使用std::list
访问列表中最近添加的项,并保留单个元素的地址是的,列表允许您访问O(1)
中的第一个和最后一个元素。太棒了。我看不出任何问题。我使用的是std::list words;和{words.push_back(v);last_added2=&words.back();}+1,这是一种显而易见的方式,不会保存可能失效的临时表(或者使用words.back()
)。我需要返回指向元素的指针,而不是元素的副本。谢谢。但我将使用peoro的解决方案,其中包括列表。这是一种非常复杂的方法。如果它能够工作,这是一个很好的答案,因为它保留了向量的使用和存储的接口。使用索引号是一个好主意,但对于更大的pr来说不起作用这是一个简化的问题。我正在使用您和peoro的std::list解决方案。