复制时出现 MSVC 12 std::initializer_list 错误 std::string
MSVC 12 std::initializer_list bug when copying std::string
我正在尝试使用 MSVC 12(Visual Studio 2013,更新 4)创建一个 C++ 程序,它使用 std::initializer_list
个具有 std::string
个成员的结构。我似乎 运行 进入了 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 - The array has the same lifetime as any other temporary object (12.2), except that initializing an initializer_list
object from the array extends the lifetime of the array exactly like binding a reference to a temporary [...]
请注意,clang 在这一点上同意 MSVC; gcc 对支持数组执行生命周期延长,但这样做是错误的(提交错误:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66476)。
如果你想要复制初始化(延长生命周期),使用等号:
std::initializer_list<TestStructure> structures = {structure};
否则,使用direct-list-initialization(直接使用大括号):
std::initializer_list<TestStructure> structures{structure};
我正在尝试使用 MSVC 12(Visual Studio 2013,更新 4)创建一个 C++ 程序,它使用 std::initializer_list
个具有 std::string
个成员的结构。我似乎 运行 进入了 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 - The array has the same lifetime as any other temporary object (12.2), except that initializing an
initializer_list
object from the array extends the lifetime of the array exactly like binding a reference to a temporary [...]
请注意,clang 在这一点上同意 MSVC; gcc 对支持数组执行生命周期延长,但这样做是错误的(提交错误:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66476)。
如果你想要复制初始化(延长生命周期),使用等号:
std::initializer_list<TestStructure> structures = {structure};
否则,使用direct-list-initialization(直接使用大括号):
std::initializer_list<TestStructure> structures{structure};