使用std::vector emplace_back()结合带构造初始化列表的std::pair异常问题
问题分析与解决:emplace_back初始化ofVec3f pair时的错误赋值
嘿,这个问题我之前也碰到过!核心原因是你误用了C++里的逗号表达式,导致初始化逻辑完全偏离了预期。
为什么会出现错误赋值?
你写的(1.0f, 2.0f, 3.0f)并不是给ofVec3f构造函数传递三个参数——这是C++的逗号表达式:它会依次计算每个子表达式,最终只返回最后一个子表达式的值(也就是3.0f)。
结合你的ofVec3f类来看,它应该存在一个单参数构造函数(比如ofVec3f(float v) : x(v), y(v), z(v) {},或者带默认参数的三参数构造函数),所以编译器会用这个单个的3.0f去初始化第一个ofVec3f对象,最终导致Geometry[0].first的x、y、z全是3.0f,完全不符合你的预期。
VS2017能编译通过,是因为它对隐式转换和逗号表达式的处理比较宽松,允许用单个float构造ofVec3f,但这其实是一个逻辑漏洞。
三种解决方法
1. 显式构造ofVec3f对象
直接用花括号初始化ofVec3f,明确告诉编译器调用三参数构造函数:
Geometry.emplace_back(ofVec3f{1.0f, 2.0f, 3.0f}, ofVec3f{4.0f, 5.0f, 6.0f});
2. 简洁的花括号转发写法
emplace_back会把参数转发给std::pair的构造函数,而pair可以直接接受两个ofVec3f的初始化列表,所以可以省略显式的类型名:
Geometry.emplace_back( {1.0f, 2.0f, 3.0f}, {4.0f, 5.0f, 6.0f} );
3. 使用piecewise_construct(复杂场景适用)
如果你的ofVec3f构造需要更灵活的参数转发,可以用std::piecewise_construct分别构造pair的两个元素(需要包含<tuple>头文件):
#include <tuple> Geometry.emplace_back(std::piecewise_construct, std::forward_as_tuple(1.0f, 2.0f, 3.0f), std::forward_as_tuple(4.0f, 5.0f, 6.0f));
关键提醒
在C++中,圆括号包裹的多值逗号分隔会被解析为逗号表达式,而不是构造函数的参数列表。要初始化带多参数的对象,优先用花括号{}来明确表示初始化列表,或者显式构造对象。
内容的提问来源于stack exchange,提问作者Castaa
相关产品推荐
相关产品推荐

