[英]MSVC 12 std::initializer_list bug when copying std::string
我正在尝试使用MSVC 12(Visual Studio 2013,Update 4)创建一个C ++程序,该程序使用具有std::string
成员的结构的std::initializer_list
。 我似乎遇到了MSVC中的错误。 这是一个显示问题的最小示例:
#include <cassert>
#include <initializer_list>
#include <string>
namespace
{
struct TestStructure
{
std::string m_string;
int m_integer;
TestStructure(const std::string& string, int integer)
: m_string(string), m_integer(integer)
{
}
TestStructure(const TestStructure&) = default;
~TestStructure() = default;
TestStructure& operator=(const TestStructure&) = default;
};
}
int main(int, char **)
{
TestStructure structure("foobar", 12345);
std::initializer_list<TestStructure> structures({structure});
assert(structure.m_integer == 12345);
assert(structure.m_string == "foobar");
assert(structures.size() == 1);
assert(structures.begin()->m_integer == 12345);
assert(structures.begin()->m_string == "foobar"); // abort()'s here.
return EXIT_SUCCESS;
}
我希望该程序可以编译并执行而不会出现任何问题。 但是,当我运行它时,最后一个断言似乎失败了。 在Visual Studio调试器中查看,似乎structures.begin()->m_string == ""
。
我的程序是否格式不正确,或者实际上是MSVC中的错误? 是否有解决此问题的方法(除了不使用初始化列表以外)?
问题是您同时使用括号和花括号:
std::initializer_list<TestStructure> structures({structure});
^^ ^^
这将构造一个临时的std::initializer_list<TestStructure>
并将其复制到structures
; 正常的生存期延长将不会执行,因此structures
将指向已破坏的存储:
[dcl.init.list] :
6-数组具有与任何其他临时对象(12.2)相同的生存期,只不过从数组
initializer_list
对象可以延长数组的生存期,就像将引用绑定到临时[...]
请注意,clang在这方面与MSVC一致; gcc在支持阵列上执行生命周期扩展,但是这样做是错误的(提起错误: https : //gcc.gnu.org/bugzilla/show_bug.cgi? id =66476 )。
如果要复制初始化(具有生存期扩展),请使用等号:
std::initializer_list<TestStructure> structures = {structure};
否则,请使用直接列表初始化(直接使用花括号):
std::initializer_list<TestStructure> structures{structure};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.