C ++如何使用指向向量指针的指针

Posted

技术标签:

【中文标题】C ++如何使用指向向量指针的指针【英文标题】:C++ how to work with pointers to vector pointers 【发布时间】:2019-01-09 18:49:59 【问题描述】:

我有这个设计:

vector<string*>* tmp = new vector<string*>;

如何将元素放入其中? 我不明白我是如何在这个向量中放入一些字符串的。 我试过了

std::string srt = "abc";
tmp->push_back(srt);

但是编译器会诅咒,语法不正确,不知道怎么办

【问题讨论】:

直接用vector&lt;string&gt;就行了 @Justin 我不明白如何 您可以将指针推回字符串。 tmp-&gt;push_back(&amp;str); 但是如果你不了解指针、动态分配及其背后的机制以及这里需要使用共享指针,那么没有什么能拯救你。 那里不需要两个指针。 std::vector&lt;std::string&gt; 会对你有好处,就像它对你之前的数百万满意的客户一样。 @user9431986 我不明白如何 -- 让我感到奇怪的是为什么你会认为std::vector&lt;std::string*&gt;* 比简单地使用std::vector&lt;std::string&gt; 更容易使用。 【参考方案1】:

只是不要太指针式(假设这是一个相对简单的程序)

vector<string> tmp;
std::string srt = "abc";
tmp.push_back(srt);

当然,指向字符串的指针向量是一场等待发生的灾难。而且可能你也不需要指向向量的指针

【讨论】:

【参考方案2】:

语法是tmp-&gt;push_back(&amp;srt);

但最好使用vector&lt;string&gt;,因为向量会为您处理指针。

喜欢:

std::vector<std::string> tmp;
std::string srt"abc";
tmp.push_back(srt);

【讨论】:

tmp-&gt;push_back(&amp;srt) 会编译,但会抛出运行时错误:至少在 Visual Studio 中出现访问冲突错误。 @FrancisCugler 它在 Visual Studio 上对我来说没有错误。您是如何读取该值的?你可以使用*((*tmp)[0]) @Wally 啊好吧,我忘记了指向vector的实际指针上的double indirection...【参考方案3】:

回答你的问题:

如何使用指向向量指针的指针?

让我们看一个基本的例子......

#include <iostream>
#include <string>
#include <vector>

int main() 
    // has to be initialized since it is a pointer.
    // However, this will compile but will fail at runtime.
    std::vector<std::string*>* pvWords = nullptr;

    std::string word1 = "Hello";
    std::string word2 = "World";

    // Here you need the `operator->()` from the vector
    // and since it will store pointers to strings,
    // you can just pass in the address of...
    pvWords->push_back( &word1 ); 
    pvWords->push_back( &word2 );

    for ( auto& s : *pvWords )    // here we need to dereference pvWords
        std::cout << *s << ' ';   // and here we need to dereference s
    std::cout << '\n';

    return 0;

-预期输出-

Hello World

但是,这将编译但在运行时会失败,并导致 Visual Studio 中出现访问冲突错误。这会失败,因为一旦strings 指针超出范围,它们就会被销毁,并且vectorvector* 试图引用的内存现在无效。您也许可以通过使用动态内存来解决这个问题,但即便如此,它只会使代码更复杂、更难管理,并可能导致更多看不见的错误。

如果我们将上述修复为以下 sn-p,则代码将起作用:

#include <iostream>
#include <string>
#include <vector>

int main() 
    std::vector<std::string*>* pvWords = new std::vector<std::string*>;
   
    std::string word1 = "Hello";
    std::string word2 = "World";

    pvWords->push_back( &word1 ); 
    pvWords->push_back( &word2 );

    for ( auto& s : (*pvWords) )
        std::cout << (*s) << ' ';
    std::cout << '\n';

    delete pvWords; // don't forget to cleanup dynamic memory.

    return 0;

这将与动态内存一起使用,并将提供以下输出:

Hello World

但是,为了避免所有这些错误和代码的复杂性,只需不要使用任何指针,尤其是在使用 std::string 时。



第一个解决方案可以工作,但如果任何指针在使用前变为无效,并且很难避免运行时错误,则可能会导致问题。

在这种情况下不需要使用指针。您没有在需要继承或多态性的地方存储基类的派生类。

由于std::vectorstd::string 的行为,只需这样做:

#include <iostream>
#include <string>
#include <vector>

int main() 
    std::vector<std::string> vWords;

    vWords.push_back( "Hello" );
    vWords.push_back( "World" );

    for ( auto& s : vWords )
        std::cout << s << ' ';
    std::cout << '\n';

    return 0;

由于std::vectorstd::string 管理它们自己的内存,因此将产生相同的预期结果,无需任何动态内存分配和内存清理、没有任何错误和任何代码复杂性。

-输出-

Hello World

此版本的代码更易于阅读、更易于使用和调试,更易于其他人使用,并且完全符合您的预期。此解决方案非常简单、快速且高效,没有任何麻烦。

【讨论】:

pvWords 被初始化为 nullptr。你无法访问它。第二个代码块无法编译。离开= nullptr @doug 我是这么认为的,但是由于某种原因,如果我不初始化它,我会遇到编译器错误... 您有两个程序。如果您省略了= nullptr,但您在“Hello”和“World”字符串的末尾省略了分号,则第一个不会编译。第二个不会按原样编译,但是如果您从第二个中删除= nullptr,它将正确编译和运行。第一个编译(除了半编译)但没有运行的原因是它需要用new vewctor&lt;string&gt;();初始化,而不是nullptr。如果你这样做,它也会编译并运行。 @doug,缺少的分号是错字。感谢您指出这一点。 我认为这只是一个错字。从 *** 复制代码并编译它以检查拼写错误是个好主意。我在我发布的帖子中找到了一些内容,它可以帮助其他尝试复制问题的人。特别是对于那些刚接触 C++ 的人。这种语言有时会令人生畏。【参考方案4】:

在没有令人信服的理由的情况下,可以但不应该以你的方式使用矢量,我想不出一个。

vector&lt;string*&gt;* tmp = new vector&lt;string*&gt;;

你必须这样做:

using std::vector; using std::string; using std::cout;

int main()

    vector<string*>* tmp = new vector<string*>;
    string srt = "abc";
    (*tmp).push_back(&srt);
    cout << *(*tmp)[0] << endl;
    delete tmp;

或者,可以使用间接运算符-&gt; 而不是*。他们做同样的事情,但在不同的地方看起来都很丑。

    tmp->push_back(&srt);
    cout << *tmp->operator[](0) << endl;

让我们看看*(*tmp)[0] 发生了什么。 (*tmp)tmp 指向的向量。 (*tmp)[0] 是向量中第一个元素的内容,它是指向字符串的指针。 *(*tmp)[0] 是向量中第一个元素所指向的字符串。

除了有点晦涩难懂的语法之外,请注意向量中的元素指向的字符串超出范围会产生悬空指针。

这是使用容器存储字符串的规范方式。

int main()

    vector<string> tmp;
    string srt = "abc";
    tmp.push_back(srt);
    cout << tmp[0] << endl;

【讨论】:

以上是关于C ++如何使用指向向量指针的指针的主要内容,如果未能解决你的问题,请参考以下文章

C语言中如何显示指针所指向的数

C语言如何声明一个返回函数指针的函数?

C语言如何定义指针指向字符型二维数组

指向抽象类的指针

用向量 c++ 中的指针成员初始化对象

指针指针!!