C++ 将地址保存为字符串的向量转换为新的向量

C++ Convert a vector which has a address held as a string, into a new Vector

本文关键字:向量 转换 地址 C++ 字符串 保存      更新时间:2023-10-16

我可以得到一些建议吗? 我不是将函数中的向量作为指针或引用返回,而是将其作为包含地址的字符串返回。(我有充分的理由(。

^那部分是成功的,我似乎想不通的部分是,如何获取返回的字符串(其中包含向量的地址(并用它制作一个新向量。

这是从函数在包含其内存地址的字符串中传递的向量(结构类型(:

vector<intructor> intruct;

将向量的地址转换为字符串:成功

string address;
stringstream ss;
ss << &depart;
ss >> address;
return address;

我尝试将其转换回新矢量:失败

vector<intructor> getIntructorVector(string filePath)
{
stringstream ss;
string address = VectorCreator(filePath);
vector<intructor> intruct;
ss << address;
ss >> &intruct;
return intruct;
}

如果你需要知道,这就是向量所包含的内容:

struct intructor {
string name;
string dept;
int id;
};

我会给出传统的 StackOverflow 警告"你可能实际上并不想这样做"——在现代C++中,通常不鼓励手动操作指针,并且在分配对象和传递包含其地址的字符串之间可能会发生很多坏事。话虽如此,这是你的问题:

&intruct,intruct的地址,是一个右值 - 你不能写入它。您当前的代码实质上是执行以下操作:

{
stringstream ss;
string address = VectorCreator(filePath);
vector<intructor> intruct;
vector<intructor>* intructPtr = &intruct;
ss << address;
ss >> intructPtr; // intruct has not been changed
return intruct;
}

由于您的函数返回的是向量(而不是指向向量的引用或指针(,因此您似乎想要创建指向的向量的副本。在这种情况下,您需要将其分为两个步骤:

{
stringstream ss;
string address = VectorCreator(filePath);
vector<intructor>* intructPtr;
ss << address;
ss >> intructPtr; // intructPtr now points to the resource from VectorCreator
return *intructPtr; // returns a copy of the resource from VectorCreator
}

如果你不想做一个副本,那么你的函数应该返回一个引用vector<intructor>&或指针vector<intructor>*——尽管你所做的一切都非常危险,很容易最终引用或指向一个无效的位置,从而隔离你的程序。

如果无法使 VectorCreator 返回智能指针或矢量本身,请非常小心,在创建副本之前,不要删除或增长矢量(可能导致重新分配(。

这一切似乎有点非正统的tbh。它可以工作,但前提是您确定原始载体在整个过程中保持有效。毕竟,字符串中的地址仅指向原始向量。

struct intructor {
std::string name;
std::string dept;
int id;
};
std::string vec_to_address(std::vector<intructor> const& v)
{
std::ostringstream oss;
oss << &v;
return oss.str();
}
std::vector<intructor>* address_to_vec_ptr(std::string const& s)
{
void* vp;
std::istringstream(s) >> vp;
return reinterpret_cast<std::vector<intructor>*>(vp);
}
int main()
{
std::vector<intructor> v;
v.push_back({"Name A", "Dept A", 1});
v.push_back({"Name B", "Dept B", 2});
v.push_back({"Name C", "Dept C", 3});
auto address = vec_to_address(v);
auto pointer = address_to_vec_ptr(address);
for(auto const& i: *pointer)
std::cout << i.name << 'n';
// if you want a copy of the original vector you can do that
// like this:
auto copy_of_original = *pointer;
}

输出:

Name A
Name B
Name C

尝试这样的事情:

std::vector<intructor> getIntructorVector(std::string filePath)
{
std::string address = VectorCreator(filePath);
std::istringstream iss(address);
void *intruct;
ss >> intruct;
return *static_cast<std::vector<intructor>*>(intruct);
}

若:

  1. 您不会跨进程边界传递std::string。 一个进程欠的内存地址在另一个进程中无效。

  2. 调用getIntructorVector()时,原始std::vector在内存中仍处于活动状态,否则您将有一个悬空指针,因此取消引用它将是未定义的行为。

如果这些假设中的任何一个都不成立,那么你试图做的事情就不能以这种方式完成。 你必须将整个vector数据序列化string,然后将字符串反序列化vector,例如:

std::ostream& quoted(std::ostream &out, const std::string &s)
{
out << '"';
for(size_t x = 0; x < s.size(); ++x)
{
char c = s[x];
if ((c == '"') || (c == ''))
out << '';            
out << c;
}
out << '"';
return out;
}
...
size_t size = intruct.size();
std::ostringstream oss;
oss << size;
for(size_t x = 0; x < size; ++x)
{
intructor &i = intruct[x];
out << ' '; quoted(out, i.name);
out << ' '; quoted(out, i.dept);
out << ' ' << i.id;
}
return oss.str();

std::istream& unquoted(std::istream &in, std::string &s)
{
if (in >> std::ws)
{
if (in.peek() == '"')
{
in.ignore();
s.clear();
char c;
while (in.get(c))
{
if (c == '')
{
if (!in.get(c))
break;
}
else if (c == '"')
break;
s += c;
}
}
else
in >> s;
}
return in;
}
vector<intructor> getIntructorVector(string filePath)
{
string data = VectorCreator(filePath);
istringstream iss(data);
string s;
size_t size = 0;
iss >> size;
vector<intructor> intruct;
intruct.reserve(size);
for(size_t x = 0; x < size; ++x)
{
intructor i;
unquoted(iss, i.name);
unquoted(iss, i.dept);
iss >> i.id;
if (!iss) break;
intruct.push_back(i);
}
return intruct;
}