动态创建矢量并在 C++ 中添加到地图

Posted

技术标签:

【中文标题】动态创建矢量并在 C++ 中添加到地图【英文标题】:Create vector dynamically and add to map in C++ 【发布时间】:2019-08-04 02:51:41 【问题描述】:

假设我有一个问题陈述,其中我的函数接收一个字符串(所有字母),我需要存储所有字母的索引。例如

If input is aabbacd
then I need something like
a -> 0, 1, 4
b -> 2, 3
c -> 5
d -> 6

现在,我想创建一个 char 到 vector 的映射,但最终创建了一个 char 到 vector* 的映射。

function(String s)

    map<char, vector<int> > m;
    for(i = 0; i < s.size(); i++)
    
        if(m.find(s[i]) == m.end())
        
            //create new vector and push 'i'
            vector<int>* v = new vector<int>(); // If I create a vector here, then that will only be live till the closing brace of the if
            .... // rest of the code

鉴于 c++ stl 已经处理了所有指针管理,我知道创建一个 vector* 并不是最好的事情。但是在这种情况下我能做些什么,以便在 if 块内创建的向量也保持在外面?

【问题讨论】:

只需将矢量插入地图即可。或者甚至更好,而不是您的 m.find(),只需执行 m[s[i]].push_back(i) 请修正您的代码。 function(String s) 看起来不像 C++。并且没有声明i 【参考方案1】:

STL 容器按值保存元素,即,它会复制您要使用的向量。因此,您担心向量超出范围在很大程度上是徒劳的。只需创建一个法线向量并将其移动到容器中。示例:

map<char, vector<int>> m;
for (std::size_t i = 0; i < s.size(); ++i) 
    vector<int> v;
    // populate v
    m.emplace(character, std::move(v));
    // now m holds its own *copy* of the vector

事实上,您似乎使这个过程过于复杂。它可以很简单:

map<char, vector<std::size_t>> m;
for (std::size_t i = 0; i < s.size(); ++i)
    m[s[i]].push_back(i);
return m;

感谢cplusplusrat。

【讨论】:

如果我不是m.emplace,而是m.insert(character, v),会导致任何问题。如果是,那会是什么?我认为不会,因为 insert 在插入时仍会复制内容,而 emplace 只是取消复制过程并窃取向量的副本。让我知道我是否在这里。谢谢 @Kraken 是的,它会导致程序格式错误,因为insert 不能这样使用:-) 另外,复制被std::move 消除了。 :),如果我在创建字符对、向量方面遵循正确的语法,那怎么样? @Kraken emplace 只是 insert 的一个包装器,它使用完美转发让您可以简单地将参数传递给构造函数并在内部调用构造函数。如果使用insert,则必须手动调用构造函数。【参考方案2】:

std::mapis to create a value at that key if none previously existed的默认行为:

返回对与特定键关联的对象的引用。如果地图尚未包含此类对象,则 operator[] 插入默认对象 data_type()。

也就是说,仅通过引用m[myChar],如果之前不存在,您将在该位置创建一个空向量。无需使用new 创建一个。

相反,解决方案非常简单:

void function(string s) // note, before you didn't specify a return type That's bad.
                            // In real C++ code, always specify a return type, or void if none
    // also, I'm assuming you're using an std::string, which is not String even with
    // using namespace std (bad idea to use that, btw)

    map<char, vector<int> > m;
    for(unsigned int i = 0; i < s.size(); i++) // Also, i needs a type. I chose unsigned int
    
        m[s[i]].push_back(i);
    
    // do more things...


【讨论】:

【参考方案3】:

但最终创建了一个 char 到 vector* 的映射。”

代码中没有这样的东西。看来您刚刚创建了内存泄漏。

但是在这种情况下我能做些什么,以便在 if 块内创建的向量也保持在外面?

你不需要做任何事情,也不需要让向量保持活动状态。 std::map 存储您放入其中的任何内容的副本。你可以建立你的向量,把它放在地图中,然后忘记它,因为地图存储了一个副本;或者您可以直接在地图中构建矢量:

for(i = 0; i < s.size(); i++)
    m[s[i]].push_back(i);

如果您正在处理英文字母表和 ASCII,看起来就是这种情况,您可能希望完全放弃映射并使用 26 个向量的数组。代码几乎保持不变:

for(i = 0; i < s.size(); i++)
    m[s[i] - 'a'].push_back(i);

(假设字符串是小写的)。

【讨论】:

以上是关于动态创建矢量并在 C++ 中添加到地图的主要内容,如果未能解决你的问题,请参考以下文章

React 中的动态表单,无法读取未定义的属性“地图”

如何从 CUDA C++ 创建和使用动态库“.so”并在 Linux 环境 (CentOS) 下的 C# 代码中使用它?

C++语言动态创建对象

动态创建列表并在每个新创建的元素中添加 HTML 标签

PaintCode,如何在矢量的一部分周围添加一个框架并让它动态调整大小?

11openlayers 地图交互