将矢量引用复制到另一个
Posted
技术标签:
【中文标题】将矢量引用复制到另一个【英文标题】:Copying a vector reference to another 【发布时间】:2011-01-13 04:58:31 【问题描述】:我有一个结构,比如 SubscriptionData。该类型的两个变量在函数 1 中声明。
SubscriptionData aSubscriptionData;
SubscriptionData aResultSubscriptionData;
结构本身具有另一个结构,而该结构又具有另一个结构的向量。向量在下面给出
aSubscriptionData.apn_config_file.apn_config
我已正确初始化结构。现在,我调用一个函数来填充 aSubscriptionData。然后我调用另一个函数,其原型如下所示。
void breakSubDataLen(ImsMsg::SubscriptionData& aSubscriptionData, ImsMsg::SubscriptionData& aResultSubscriptionData);
在函数breakSubDataLen()中,我应该将aSubscriptionData.begin()+3到aSubscriptionData.end()的元素复制到aResultSubscriptionData结构中。
我正在为此做以下操作。
std::copy(aSubscriptionData.apn_config_file.apn_config.begin() + 3,
aSubscriptionData.apn_config_file.apn_config.end(),
aResultSubscriptionData.apn_config_file.apn_config.begin());
它似乎不起作用。谁能帮帮我?
【问题讨论】:
我很抱歉这里有错误的代码 sn-p。实际的行是 std::copy(aSubscriptionData.apn_config_file.apn_config.begin()+3, aSubscriptionData.apn_config_file.apn_config.end(), aResultSubscriptionData.apn_config_file.apn_config.begin()); 已为您修复。顺便说一句,apn_config
是 std::vector
,对吧?
“它似乎不起作用”是一个模糊的问题描述。
是的.. apn_config 是一个 std::vector。我正在尝试您的解决方案。
成功!! @James:非常感谢伙计!
【参考方案1】:
std::copy
不分配元素;您必须确保目标范围中有足够的空间来容纳源范围中的所有元素。
执行此操作的常用方法是使用std::back_inserter
,它调用push_back
将每个元素插入容器:
std::copy(source.begin(), source.end(), std::back_inserter(destination));
另一种常见的方法是使用resize
在目标序列中预先分配足够的空间:
destination.resize(std::distance(source.begin(), source.end()));
std::copy(source.begin(), source.end(), destination.begin());
当然,这两种方法具有不同的行为。使用std::back_inserter
,将保留序列中的任何元素,并在现有元素之后插入新元素。使用resize
方法,任何现有元素都会被覆盖。您还可以使用resize
方法并保留任何现有元素:
const std::size_t original_size = destination.size();
destination.resize(destination.size() +
std::distance(source.begin(), source.end());
std::copy(source.begin(), source.end(), destination.begin() + original_size);
(这要求destination
是像std::vector
这样的随机可访问容器;如果不是,则必须相应地修改代码。)
【讨论】:
resize
方法还会对输入进行两次迭代,如果迭代有副作用,例如从非搜索文件中消耗数据,这可能很重要。
@Mike:是的,确实如此;源迭代器需要是 ForwardIterator(因为 OP 有一个容器,所以几乎可以肯定源范围是可前向迭代的)。
vector 的范围插入函数不应该本质上做到这一点,并且更有效吗?
@JaredC:是的,这绝对更干净(+1),但我不确定它是否会更有效。如果源是 InputIterator 范围,则该向量要么需要使用 back_inserter
方法,要么需要累积到辅助存储中,然后使用 resize 方法(我不是 100% 肯定这种方法会被严格允许)。如果源是 ForwardIterator 范围,则可以直接使用 resize 方法。
效率问题是一个有趣的问题,因为标准库实现者针对他们认为的“常见情况”进行了优化。我现在正在编写一个词法分析器生成器,它有一个转换迭代器,可以将字符序列转换为标记序列。实际的标记化过程相对昂贵,所以最好只做一次。使用 std::vector
的 Visual C++ 实现,如果我将 insert(...)
与我的 ForwardIterator 一起使用,它会执行两次标记化:一次调用 std::distance
以计算序列中的元素数,然后【参考方案2】:
通过将aResultSubscriptionData.apn_config_file.apn_config.begin()
作为第三个参数传递给std::copy
,您是在告诉它您已经为它分配了足够的空间来分配从.begin()
开始的元素。如果向量中有 0 个元素,那么很明显 .begin()
或 .begin() + X
没有引用有效的迭代器。如果向量已经包含足够的元素,或者如果它被调整大小,这将起作用,在这种情况下,它将元素复制到新的向量中。
您想使用的很有可能是使用vector
s 范围插入。我相信它会更有效率:
aResultSubscriptionData.apn_config_file.apn_config.insert(0, aSubscriptionData.apn_config_file.apn_config.begin() + 3, aSubscriptionData.apn_config_file.apn_config.end());
【讨论】:
以上是关于将矢量引用复制到另一个的主要内容,如果未能解决你的问题,请参考以下文章
在javascript中将对象数组复制到另一个数组而没有对象引用(深拷贝)