【问题标题】:A few C++ vector questions几个 C++ 向量问题
【发布时间】:2013-01-18 19:49:08
【问题描述】:

我正在尝试学习一些 c++,首先我创建了一些方法来处理控制台的输出和读取。 我有 2 个主要问题,在代码中标记,操作/访问通过引用传入的字符串的 std::vector 中的值。

下面的方法接受一个问题(标准字符串)来询问用户和一个向量标准字符串,其中包含用户认为可接受的响应。为了学习,我还想访问向量中的字符串并更改其值。

std::string My_Namespace::My_Class::ask(std::string question, std::vector<std::string> *validInputs){
    bool val = false;
    std::string response;
    while(!val){
        //Ask and get a response
        response = ask(question);
        //Iterate through the acceptable responses looking for a match
        for(unsigned int i = 0; i < validInputs->size(); i++){
            if(response == validInputs->at(i)){
                ////1) Above condition always returns true/////
                val = true;
                break;
            }
        }
    }
//////////2) does not print anything//////////
println(validInputs->at(0)); //note the println method is just cout << param << "\n" << std::endl
//Really I want to manipulate its value (not the pointer the actual value)
//So I'd want something analogous to validInputs.set(index, newVal); from java
///////////////////////////////////////////
}

几个额外的问题:

3) 我在向量上使用 .at(index) 来获取值,但我已经读到应该使用 [] 来代替,但是我不确定它应该是什么样子(validInputs[i ] 无法编译)。

4) 我认为由于不需要深拷贝,因此最好将指针传递给上述向量,有人可以验证吗?

5) 我听说 ++i 在循环中比 i++ 更好,是真的吗?为什么?

【问题讨论】:

    标签: c++ string pointers vector


    【解决方案1】:

    3) 在这种情况下,使用atoperator[] 应该没有显着差异。请注意,您有一个指向向量的指针,而不是向量(也不是指向向量的引用),因此您必须使用 (*validInputs)[i]validInputs-&gt;operator[](i) 来使用运算符重载。如果您不想使用这些其他方法中的任何一种,使用 validInputs-&gt;at(i) 就可以了。 (如果参数超出数组边界,at 方法将抛出异常,而当参数超出数组边界时,operator[] 方法具有未定义的行为。由于operator[] 跳过了边界检查,所以它是如果您知道事实更快,i 在向量的范围内。如果您不确定,请使用 at 并准备捕获异常。)

    4) 指针很好,但引用会更好。而且,如果您不修改方法中的向量,则最好使用对 const 向量的引用 (std::vector&lt;std::string&gt; const &amp;)。这可以确保您不会被传递一个空指针(引用不能为空),同时也确保您不会意外修改向量。

    5) 通常是这样。 i++ 是后自增的,表示必须复制原始值,然后将i 自增,返回原始值的副本。 ++i 递增i 然后返回i,因此通常更快,尤其是在处理复杂的迭代器时。使用unsigned int,编译器应该足够聪明,可以意识到预增量会很好,但是如果您不需要i 的原始未增量值,那么最好开始使用++i。 .

    【讨论】:

    • 没有显着差异?一个抛出异常,另一个调用未定义的行为......我称之为重要
    • @K-ballo 在其他情况下很重要;我专门指的是这个,我们知道i 在范围内。但我会编辑我的答案以包含这种差异。
    【解决方案2】:

    我会使用对 const 的引用和std::find。请注意,我还通过引用获取字符串(否则它会被深度复制):

    std::string My_Class::
    ask (const std::string& question, const std::vector<std::string>& validInputs)
    {
        for (;;) {
            auto response = ask (question);
            auto i = std::find (validInputs.begin (), validInputs.end (), response);
    
            if (i != validInputs.end ()) {
                 std::cout << *i << '\n'; // Prints the value found
                 return *i;
            }
        }
    }
    

    如果您不了解代码,请阅读迭代器。当然,如果您需要,请随时提出其他问题。

    【讨论】:

      【解决方案3】:

      我不打算讨论第 1 点和第 2 点,因为我们不知道您在做什么,我们甚至看不到 askprintln 的代码。

      我在向量上使用 .at(index) 来获取值,但我读过应该使用 [] 来代替,但是我不确定它应该是什么样子(validInputs[i] 没有'不编译)。

      下标访问和at 成员函数是不同的东西。它们给你同样的东西,一个对索引元素的引用,但是如果你传递一个越界索引,它们的行为会有所不同:at 将引发异常,而[] 将调用未定义的行为(就像内置数组一样) .在指针上使用[] 有点难看,(*validInputs)[i],但您确实应该尽可能避免使用指针。

      我认为由于不需要深度复制,因此最好将指针传递给上述向量,有人可以验证吗?

      深拷贝是不必要的,但指针也是如此。你需要一个参考,还有一个const,因为我认为你不应该修改这些:

      ask(std::string const& question, std::vector<std::string> const& validInputs)
      

      我听说 ++i 在循环中比 i++ 更好,是这样吗?为什么?

      在一般情况下是这样。这两个操作是不同的,++i 递增i 并返回新值,而i++ 递增i 但返回递增前的值,这需要临时保持并返回。对于ints,这几乎无关紧要,但对于潜在的胖迭代器来说,如果您不需要或不关心它的返回值,则预增量是更有效和更好的选择。

      【讨论】:

        【解决方案4】:

        要回答问题 1 和 2,我们可能需要更多信息,例如:您是如何初始化 validInputs 的?问的来源是什么?

        3) 先解引用指针,再索引向量:

        (*validInputs)[i]
        

        4) 引用被认为是更好的风格。尤其是代替从不为 NULL 的指针。

        5) 对于整数,没关系(除非你计算表达式的结果)。对于其他对象,使用重载的 ++ 运算符(例如迭代器)可能会更好地使用 ++i。但实际上,对于 ++ 运算符的内联定义,它可能会优化为相同的代码。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-07
          • 1970-01-01
          相关资源
          最近更新 更多