【问题标题】:Is there anyway to initialize an object from an outer scope in an inner scope?无论如何要在内部范围内从外部范围初始化对象吗?
【发布时间】:2011-04-25 20:19:23
【问题描述】:

例如:

int main()
{
    {
        // I want this array to be part of the inner scope
        string s[] = {"Ben","Joe","Bob","Matt"};

        // And I want to use it to initialize this vector, but I want this
        // vector to be visible in the outer scope
        vector<string> names(s,s+4);
    }
}

有什么办法吗?

【问题讨论】:

    标签: c++ scope initialization


    【解决方案1】:

    如果您希望向量在外部范围内可见,您必须在外部范围内声明它。这意味着您还必须在那里对其进行初始化。 在不初始化的情况下声明它的唯一方法是使用指针:

    int main()
    {
      vector<string> * names = 0;
    
      {
        string s[] = {"Ben", "Joe", "Bob", "Matt"};
        names = new vector<string>(s, s+4);
      }
    
      // ...
      delete names;
    }
    

    【讨论】:

      【解决方案2】:
      int main()
      {
          vector<string> names;
          {       
              string s[] = {"Ben","Joe","Bob","Matt"};
              names.assign(s,s+4);
          }
      }
      

      【讨论】:

      • 这里,向量是在外部范围内初始化的 :) 这可能根本不是问题,但这不是问题所要求的。
      • @gnud:我知道,但我想这个问题更实际,而不是理论。虽然我当然可能是错的
      【解决方案3】:

      虽然没有严格初始化向量,但如果您希望您的对象是自动分配的而不是动态分配的,您可以将其替换为临时对象:

      {
          vector<string> names;
      
          {
              string s[] = {"Ben","Joe","Bob","Matt"};
      
              vector<string> init (s,s+4)
      
              swap ( names, init );
          }
      }
      

      虽然你仍然得到主要副本(复制 char* 文字以构造数组中的 std::strings,然后将数组中的 std::strings 复制到向量),但交换避免了从 init 到名称的字符串。

      【讨论】:

        【解决方案4】:

        ldx 提到指针给了我一个想法。我以前从未使用过 shared_ptr,但我认为这可能是解决方案,所以我查了一下,我想出了这个解决方案:

        编辑:改为auto_ptr

        int main()
        {
            auto_ptr<vector<string> > vsptr;
        
            {
                string s[] = {"Ben", "Joe", "Bob", "Matt"};
                int cnt = sizeof(s)/sizeof(string);
        
                vsptr = auto_ptr<vector<string> >(new vector<string>(s,s+cnt));
            }
        
            vector<string> &names = *vsptr;
        }
        

        我用一个宣布它的构造函数、赋值和析构函数的类对其进行了测试,并且只有一个默认构造和一个销毁。当然,如果你的编译器还没有实现 tr1,这需要 boost,但是什么值得该死的编译器没有呢?

        【讨论】:

        • std::auto_ptr 在这种情况下会很好;您不会在任何地方共享指针。
        • 是的,你是对的。原来我也从未使用过 auto_ptr。
        • 确实是个好主意,但你必须小心:如果 vsptr 在名称之前超出范围,那么名称将变为无效
        【解决方案5】:

        没有办法完全按照您的要求去做。正如其他人所指出的,有几种可能性:

        1. 在内部范围之前声明向量,并在此期间填充它。这样做的缺点是向量会暂时空着,这不是一种好的风格,并且通过稍后初始化它而不是构造函数可能会有很小的开销,但是这些都不重要,因为向量无论哪种方式,都必须在某个时候构建。

          // 在此处插入代码示例,抄自其他答案(?)

        2. 在内部范围之前声明一个 scoped_ptr(或 const auto_ptr,或普通指针),并在内部范围内 new 一个向量,使用构造函数对其进行初始化,并将其分配给指针。这几乎没有缺点。你必须习惯使用 -> 而不是 .但无论如何,大多数 C++ 程序都必须在任何地方这样做。您会在内部范围之前意外使用未分配指针,但它应该会立即产生异常,因此您应该注意。

          // 在此处插入代码示例,抄自其他答案(?)

        3. 将整个内部作用域或字符串数​​组封装在一个函数中。这看起来很复杂,但老实说,我很少后悔在一个明确命名的函数中进行常量初始化。该函数可以返回数组,也可以直接返回一个向量(取决于您是否真的需要内部范围内的数据,或者只是想避免它污染外部范围)。根据您选择的方式,它可能看起来像:

          矢量我的朋友(){ 常量字符串 s[] = {"Ben","Joe","Bob","Matt"}; 返回向量(s, s + (sizeof(s)/sizeof(s[0])) ); // TODO: 改进计算 // 注意使用返回值优化 // 可能无关紧要,但如果你在乎,编译器可能会忽略其中之一或两者 // 隐含的临时向量对象。 }

          int main() { { // 做东西 // 如果 MyFriends 依赖于一些东西,如果可能的话,可能把东西移到那个 func 中 // 如果东西只需要访问 MyFriends 返回值,这里再调用一次 } 向量 vec(MYFriends());

          // 更多内容 }

        4. 如果您只想像示例 3 中那样初始化向量,我认为 C++0x 支持执行此操作的特定语法 (??)

          // 举例说明

        【讨论】:

        • 自从我问了这个问题以来,我学到了一个更好的方法来做到这一点,类似于你的第三个例子。请参阅我的第二个答案。
        【解决方案6】:

        自从我问了这个问题后,我发现了一种使用 lambda 更好的方法:

        int main()
        {
            std::vector<std::string> v = []() -> std::vector<std::string> {
                std::string s[] = {"Ben","Joe","Bob","Matt"};
                int cnt = sizeof(s)/sizeof(s[0]);
                return std::vector<string>(s,s+cnt);
            }();
        }
        

        【讨论】:

          猜你喜欢
          • 2016-06-23
          • 2021-02-01
          • 2021-08-18
          • 1970-01-01
          • 1970-01-01
          • 2019-10-14
          • 2011-05-28
          • 2018-11-30
          相关资源
          最近更新 更多