首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何设置全局容器(C++03)?

如何设置全局容器(C++03)?
EN

Stack Overflow用户
提问于 2012-12-16 16:57:59
回答 4查看 2.8K关注 0票数 4

我想定义一个全局容器(C++03),下面是我尝试过的示例代码,它不起作用。

代码语言:javascript
复制
#include <vector>
#include <string>
using namespace std;

vector<string> Aries;
Aries.push_back("Taurus");    // line 6

int main() {}

编译错误:

代码语言:javascript
复制
prog.cpp:6:1: error: 'Aries' does not name a type

似乎我可以定义一个空的全局向量,但不能填充它。在C++03中,我也不能指定初始化器,例如:

代码语言:javascript
复制
vector<string> Aries = { "Taurus" };

我是不是犯了一个错误,或者我该如何解决这个问题?

我试着在StackOverflow上搜索,看看以前是否有人回答过这个问题,但只找到了这些帖子:global objects in C++Defining global constant in C++,这对回答这个问题没有帮助。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-12-16 17:20:31

我发现了一种巧妙的解决方法来“初始化”C++03全局STL容器(实际上在main()之前“全局”执行代码)。这使用逗号运算符。请参见示例:

代码语言:javascript
复制
#include <vector>
#include <string>
#include <iostream>
using namespace std;

vector<string> Aries;

// dummy variable initialization to setup the vector.
// using comma operator here to cause code execution in global scope.
int dummy = (Aries.push_back("Taurus"), Aries.push_back("Leo"), 0);

int main() {
    cout << Aries.at(0) << endl;
    cout << Aries.at(1) << endl;
}

输出

代码语言:javascript
复制
Taurus
Leo

唯一真正的问题,如果你可以这么说,就是额外的全局变量。

票数 10
EN

Stack Overflow用户

发布于 2012-12-16 17:02:42

虽然在函数(如main)之外的声明和初始化是没有问题的,但是您不能将代码放在函数之外。您需要在初始化时设置正确的值(就像在C++11中一样),或者在main中填充全局对象:

代码语言:javascript
复制
std::vector<string> Aries;

/* ... */

int main() {
    Aries.push_back("Taurus");
    /* ... */
}

其他方式(不在main中填充向量)

单值

还有其他的方式,基本上不需要.push_back或其他代码。例如,如果Aries应仅包含一项,则可以将std::vector<T>::vector(size_t s, T t)s == 1t == "Taurus"一起使用

代码语言:javascript
复制
std::vector<string> Aries(1, "Taurus");

/* ... */

int main() { /* ... */ }

如果需要多次使用相同的值,只需调整s即可。

多个不同的值

现在这变得有点棘手了。您希望通过使用合适的构造函数来填充vectorstd::vector<T>在C++03中提供了四种不同的构造函数:

  1. std::vector<T>::vector()
  2. std::vector<T>::vector(size_t, T = T())
  3. template <class InputIt> std::vector<T>::vector(InputIt, InputIt)
  4. std::vector<T>::vector(const vector&)请注意,它们实际上都将分配器作为附加的最后一个参数,但这与我们无关。

我们可以忘记std::vector<T>::vector(),因为我们想用值填充向量,而且std::vector<T>::vector(size_t, T)不适合,因为我们想要不同的值。剩下的是模板化构造函数和复制构造函数。下面的示例说明如何使用模板化构造函数:

代码语言:javascript
复制
std::string const values[] = {"Taurus", "Ares", "Testos"};

template <class T, size_t N>
T* begin(T (&array)[N]){ // this is already in C++11, very helpful 
    return array;
}
template <class T, size_t N>
T* end(T (&array)[N]){
    return array+N;
}

std::vector<std::string> Aries(begin(values), end(values));

请注意,beginend不是必需的-我们可以简单地使用Aries(values, values+3)。但是,事情往往会发生变化,通常您会添加或删除一个值。如果您忘记更改偏移量3,您可能会忘记values的一个条目或跨边界。

然而,这个解决方案引入了一个新的全局变量,这并不是很好。让我们后退一步。我们需要values,因为我们想使用std::vector<T>::vector(InputIt, InputIt),它需要一个有效的范围。当我们使用构造函数时,范围必须是已知的,所以它需要是全局的。诅咒!但是请注意:我们的工具箱仍然包含一个构造函数,即复制构造函数。为了使用它,我们创建了一个额外的函数:

代码语言:javascript
复制
namespace {
    std::vector<std::string> initializer(){
        const std::string dummy_array[] = {"Taurus", "Ares", "Testos"};
        return std::vector<std::string>(begin(dummy_array), end(dummy_array));
    }
}

std::vector<std::string> Aries(initializer());

此示例同时使用复制构造函数和范围构造函数。您还可以创建一个临时向量,并使用std::vector<T>::push_back将其填充到函数中。

票数 10
EN

Stack Overflow用户

发布于 2013-02-21 05:09:00

我的经验是,这个“令人惊叹,但可怕”(帽子提示)的解决方案是不可预测的。您的初始化在加载时运行。您不能保证加载顺序。因此,使用该容器的所有内容都必须位于同一模块中,或者以某种方式保证在访问该容器之前加载该模块。否则,容器构造函数还没有运行,但是您的代码愉快地调用了它的访问器。

当它出错时,它会变得非常错误,并且错误依赖于编译器、平台和月亮的相位-在所有情况下,都不会给出任何关于哪里出了问题的最小线索。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13899866

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档