【问题标题】:newbie question about pointer to stl关于stl指针的新手问题
【发布时间】:2011-01-11 23:50:21
【问题描述】:

这个函数我写了

vector<long int>* randIntSequence(long int n) {
    vector<long int> *buffer = new vector<long int>(n, 0);
    for(long int i = 0; i < n; i++)
        buffer->at(i);

    long int j; MTRand myrand;
    for(long int i = buffer->size() - 1; i >= 1; i--) {
        j = myrand.randInt(i);
        swap(buffer[i], buffer[j]);
    }
    return buffer;
}

但是当我从 main 调用它时,myvec = randIntSequence(10),我看到 myvector 总是空的。要不要修改返回值?

【问题讨论】:

  • 不应该用new 分配标准容器——这有点不妥!此外,您的第一个 for 循环是无操作的。
  • 这种设计看起来很可疑。为什么要动态分配vector?您不只是在堆栈上创建它并返回它有什么特别的原因吗?随机数生成器可以抛出异常吗?您是否考虑过使用智能指针?
  • 是的,我忘记将 i 分配给缓冲区的第 i 个元素。我没有指针的问题是:如果我想在函数之外的某个时刻删除向量,它会被完全删除吗?
  • 听起来你应该改用std::random_shuffle
  • 你需要在向量上推一些东西,使用push_back

标签: c++ pointers stl vector


【解决方案1】:

swap 调用正在索引*buffer 指针,就像它是一个数组一样,并且正在交换指针。你的意思是交换向量的项目。试试这个修改:

swap((*buffer)[i], (*buffer)[j]);

其次,您的 at 调用未按您的预期设置值。您正在拉出向量中的项目,但没有将它们设置为任何内容。尝试以下语句之一:

buffer->at(i) = i;
(*buffer)[i] = i;

【讨论】:

    【解决方案2】:

    您永远不会分配给vector 中由buffer 指向的任何元素:

    for (long int i = 0; i < n; i++)
        buffer->at(i); // do you mean to assign something here?
    

    您最终会得到包含 n 零的 vector

    【讨论】:

    • 不应该是评论吗?因为你从来没有完全回答过这个问题,而是用一个问题来回答。
    【解决方案3】:

    您的问题已经得到解答,所以我将制作这个 CW,但您的代码应该是这样的。

    std::vector<long int> randIntSequence(long int n)
    {
        std::vector<long int> buffer(n);
        for(int i=0; i<n; ++i)
            buffer[i] = i;
        std::random_shuffle(buffer.begin(), buffer.end());
        return buffer;
    }
    

    绝对没有理由在这里使用指针。除非你有一些更高级的随机洗牌方法,否则你应该使用std::random_shuffle。您也可以考虑使用boost::counting_iterator 来初始化向量:

    std::vector<long int> buffer(
        boost::counting_iterator<long int>(0),
        boost::counting_iterator<long int>(n));
    

    虽然这可能有点矫枉过正。

    【讨论】:

    • 如果你的编译器支持C++0x,初始化for()循环可以替换为std::iota(buffer.begin(), buffer.end(), 0);
    • @Blastfurnace -- 很酷,我不知道那个功能。我很难推荐 boost::counting_iterator 因为它太笨拙了,但 iota 更简洁。
    【解决方案4】:

    既然问题是关于 STL 的,而你想要的只是一个带有随机条目的向量:

    std::vector<long int> v(10);
    generate( v.begin(), v.end(), std::rand ); // range is [0,RAND_MAX]
    
    // or if you provide long int MTRand::operator()()  
    generate( v.begin(), v.end(), MTRand() );
    

    但如果你想修复你的功能,那么

    • n 应该是 size_t 而不是 long int
    • 第一个循环是无操作的
    • 正如约翰所说,buffer 是一个指针,所以buffer[0] 是你的向量,而buffer[i] 代表i!=0 是垃圾。看起来你很幸运能得到一个大小为零的向量而不是一个损坏的向量!
    • 您打算进行随机洗牌吗?如果是,那么您正在围绕零进行洗牌。如果您只想生成随机条目,那么为什么不循环向量(从 0 到 buffer->size(),而不是相反!!)并分配您的随机数?

    C++ 没有垃圾收集,你可能不希望智能指针用于这些简单的东西,所以你肯定会以泄漏告终。如果原因是生成堆向量并通过指针返回是为了性能而避免复制,那么我的建议是不要这样做!以下是(几乎)完美的替代方案,无论是为了清晰还是为了性能:

    vector<T> randIntSequence( size_t n ) { 
       vector<T> buffer(n);
       // bla-bla
       return buffer; 
    }
    

    如果您认为这里有过多的复制,请阅读this 并相信您的编译器。

    【讨论】:

    • 抱歉在这里重复别人的cmets。直到我发布答案,我才意识到你的评论被评论了。
    猜你喜欢
    • 2014-05-13
    • 2011-12-09
    • 2015-09-27
    • 2023-01-08
    • 1970-01-01
    • 1970-01-01
    • 2020-08-25
    • 2011-02-03
    • 1970-01-01
    相关资源
    最近更新 更多