C++ 使用逗号运算符编译变量初始化失败
为什么以下代码中指示的行(在main()中)未编译C++ 使用逗号运算符编译变量初始化失败,c++,variable-initialization,C++,Variable Initialization,为什么以下代码中指示的行(在main()中)未编译 #include <iostream> #include <string> #include <map> template< typename _T > struct Inventory : public std::map< _T, int > { bool getat(int i, _T &t, int &n) { if ((i &l
#include <iostream>
#include <string>
#include <map>
template< typename _T > struct Inventory : public std::map< _T, int >
{
bool getat(int i, _T &t, int &n)
{
if ((i < 0) || (i >= (int)this->size())) return false;
int c=0;
typename std::map< _T, int >::iterator it = this->begin();
while ((c < i) && (it != this->end())) { c++; it++; }
t = (*it).first;
n = (*it).second;
return true;
}
Inventory &operator=(_T t) { (*this)[t]++; return *this; }
Inventory &operator,(_T t) { return operator=(t); }
};
int main()
{
int i=0, quantity;
std::string item;
//***Fails to compile:***
//Inventory< std::string > inv = "a","b","c","a","c","d","e";
Inventory< std::string > inv;
inv = "a","b","c","a","c","d","e"; //but this is fine
inv = "e","f";
while (i < (int)inv.size())
{
if (inv.getat(i, item, quantity))
std::cout << i << ": " << item << " -> " << quantity << "\n";
i++;
}
return 0;
}
#包括
#包括
#包括
模板struct清单:public std::map<\u T,int>
{
布尔盖塔特(内部i、U T&T、内部n)
{
if((i<0)|(i>=(int)this->size())返回false;
int c=0;
typename std::map<\T,int>::迭代器it=this->begin();
((c<i)& &(t!-> ->())){C++,i++;}
t=(*it)。首先;
n=(*it)。第二;
返回true;
}
Inventory&operator=(T T){(*this)[T]+;return*this;}
库存与运算符,(_T){返回运算符=(T);}
};
int main()
{
int i=0,数量;
std::字符串项;
//***未能编译:***
//存货inv=“a”、“b”、“c”、“a”、“c”、“d”、“e”;
库存<标准::字符串>库存;
inv=“a”、“b”、“c”、“a”、“c”、“d”、“e”;//但这很好
inv=“e”,“f”;
而(i<(int)存货大小()
{
if(存货获取(一、项目、数量))
std::cout这称为复制初始化。简而言之,它使用转换构造函数,然后使用复制构造函数来构造inv
,而不是像您期望的那样使用操作符=
Inventory< std::string > inv = "a","b","c","a","c","d","e";
调用默认构造函数,然后
inv = "a","b","c","a","c","d","e";
对已初始化的对象调用运算符=
。这称为复制初始化。简而言之,它使用转换构造函数,然后使用复制构造函数来构造inv
,而不是像您预期的那样使用运算符=
Inventory< std::string > inv = "a","b","c","a","c","d","e";
调用默认构造函数,然后
inv = "a","b","c","a","c","d","e";
对已初始化的对象调用运算符=
。问题在于,在一种情况下,逗号是标点符号(和
运算符重载不适用),而在另一种情况下,它是
运算符。不起作用的定义基本上是等价的
其中:
您还可以重载运算符并使用它,而不是函数
add
。但是我没有看到一个可能的运算符(),你的问题是,在一个例子中,逗号是标点符号(和
运算符重载不适用),而在另一种情况下,它是
运算符。不起作用的定义基本上是等价的
其中:
您还可以重载运算符并使用它,而不是函数
add
。但是我没有看到一个可能的运算符(是否可以创建一个可以处理这样一个随机大小的列表的构造函数?(我正在玩弄逗号运算符,以了解它可以做什么和不能做什么,以及它在哪里有用。)您的解释是错误的。在这种情况下,逗号根本不是运算符,而是分隔符:Inventory inv=“a”、“b”
与Inventory inv=“a”Inventory“b”相同
而且编译器不喜欢变量名是字符串常量。@JamesKanze虽然这是真的,但我看不出解释有什么错。@slashmais逗号运算符重载唯一能做的事情就是混淆。重载运算符的行为应该与内置运算符相对应。这意味着t您不应该重载创建序列点的运算符。(重载&&
或|
也是一个坏主意。)在逗号的情况下,还有一个问题,有时是运算符,有时是标点符号,重载只适用于运算符。@LuchianGrigore您说编译器会首先尝试从“a”、“b”、“c”、“a”、“c”、“d”、“e”创建一个临时清单
。这是错误的:它将尝试从“a”
创建一个临时变量,然后定义一个名为“b”
(这当然是非法的,因为字符串文字不能作为变量的名称)。是否可以创建一个构造函数来处理这样一个随机大小的列表?(我正在玩弄逗号运算符,以了解它能做什么和不能做什么,以及在哪里有用。)您的解释是错误的。在这种情况下,逗号根本不是运算符,而是分隔符:Inventory inv=“a”,“b”
与Inventory inv=“a”Inventory“b”相同
而且编译器不喜欢变量名是字符串常量。@JamesKanze虽然这是真的,但我看不出解释有什么错。@slashmais逗号运算符重载唯一能做的事情就是混淆。重载运算符的行为应该与内置运算符相对应。这意味着t您不应该重载创建序列点的运算符。(重载&&
或|
也是一个坏主意。)在逗号的情况下,还有一个问题,有时是运算符,有时是标点符号,重载只适用于运算符。@LuchianGrigore您说编译器会首先尝试从“a”、“b”、“c”、“a”、“c”、“d”、“e”创建一个临时清单
。这是错误的:它将尝试从“a”
创建一个临时变量,然后定义一个名为“b”
(这当然是非法的,因为字符串文字不能作为变量的名称)。如果您的编译器支持#include
,那么您可以使用库存库存存货{“a”、“b”、“c”、“a”、“c”、“d”、“e”};
。请参阅VS2012(不支持).@rubberboots:我在使用gcc;将您的建议与收集器结合起来
-詹姆斯·坎兹的答案中的想法可能会很有用。@slashmais-您不需要两者。如果您将使用的编译器都支持初始值设定项列表,那就是最好的选择。如果不支持,请使用收集器
的想法。如果您的编译器支持,请包含yo你可以使用库存库存库存{“a”、“b”、“c”、“a”、“c”、“d”、“e”};
。请参阅VS2012(不支持)。@rubberboots:我使用的是gcc;将你的建议与收集器相结合
-James Kanze回答中的想法可能很有用。@slashmais-你不需要两者兼而有之
Inventory<std::string> inv = Collector().add("a").add("b")...;
Inventory<std::string> inv = Collector("a")("b")...;