我想定义一个全局容器(C++03),下面是我尝试过的示例代码,它不起作用。
#include <vector>
#include <string>
using namespace std;
vector<string> Aries;
Aries.push_back("Taurus"); // line 6
int main() {}编译错误:
prog.cpp:6:1: error: 'Aries' does not name a type似乎我可以定义一个空的全局向量,但不能填充它。在C++03中,我也不能指定初始化器,例如:
vector<string> Aries = { "Taurus" };我是不是犯了一个错误,或者我该如何解决这个问题?
我试着在StackOverflow上搜索,看看以前是否有人回答过这个问题,但只找到了这些帖子:global objects in C++,Defining global constant in C++,这对回答这个问题没有帮助。
发布于 2012-12-16 17:20:31
我发现了一种巧妙的解决方法来“初始化”C++03全局STL容器(实际上在main()之前“全局”执行代码)。这使用逗号运算符。请参见示例:
#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;
}输出
Taurus
Leo唯一真正的问题,如果你可以这么说,就是额外的全局变量。
发布于 2012-12-16 17:02:42
虽然在函数(如main)之外的声明和初始化是没有问题的,但是您不能将代码放在函数之外。您需要在初始化时设置正确的值(就像在C++11中一样),或者在main中填充全局对象:
std::vector<string> Aries;
/* ... */
int main() {
Aries.push_back("Taurus");
/* ... */
}其他方式(不在main中填充向量)
单值
还有其他的方式,基本上不需要.push_back或其他代码。例如,如果Aries应仅包含一项,则可以将std::vector<T>::vector(size_t s, T t)与s == 1和t == "Taurus"一起使用
std::vector<string> Aries(1, "Taurus");
/* ... */
int main() { /* ... */ }如果需要多次使用相同的值,只需调整s即可。
多个不同的值
现在这变得有点棘手了。您希望通过使用合适的构造函数来填充vector。std::vector<T>在C++03中提供了四种不同的构造函数:
std::vector<T>::vector()std::vector<T>::vector(size_t, T = T())template <class InputIt> std::vector<T>::vector(InputIt, InputIt)std::vector<T>::vector(const vector&)请注意,它们实际上都将分配器作为附加的最后一个参数,但这与我们无关。我们可以忘记std::vector<T>::vector(),因为我们想用值填充向量,而且std::vector<T>::vector(size_t, T)不适合,因为我们想要不同的值。剩下的是模板化构造函数和复制构造函数。下面的示例说明如何使用模板化构造函数:
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));请注意,begin和end不是必需的-我们可以简单地使用Aries(values, values+3)。但是,事情往往会发生变化,通常您会添加或删除一个值。如果您忘记更改偏移量3,您可能会忘记values的一个条目或跨边界。
然而,这个解决方案引入了一个新的全局变量,这并不是很好。让我们后退一步。我们需要values,因为我们想使用std::vector<T>::vector(InputIt, InputIt),它需要一个有效的范围。当我们使用构造函数时,范围必须是已知的,所以它需要是全局的。诅咒!但是请注意:我们的工具箱仍然包含一个构造函数,即复制构造函数。为了使用它,我们创建了一个额外的函数:
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将其填充到函数中。
发布于 2013-02-21 05:09:00
我的经验是,这个“令人惊叹,但可怕”(帽子提示)的解决方案是不可预测的。您的初始化在加载时运行。您不能保证加载顺序。因此,使用该容器的所有内容都必须位于同一模块中,或者以某种方式保证在访问该容器之前加载该模块。否则,容器构造函数还没有运行,但是您的代码愉快地调用了它的访问器。
当它出错时,它会变得非常错误,并且错误依赖于编译器、平台和月亮的相位-在所有情况下,都不会给出任何关于哪里出了问题的最小线索。
https://stackoverflow.com/questions/13899866
复制相似问题