C++ 例外安全保证和std::move()
在一些实现过程中,我遇到了异常安全保证和使用C++ 例外安全保证和std::move(),c++,c++11,exception-safety,C++,C++11,Exception Safety,在一些实现过程中,我遇到了异常安全保证和使用std::move()的问题。我知道SO不是一个问“你的意见是什么”(类模板Boo)这类问题的好地方,但在这里,我想确定我的理解是否正确,在你阅读这个问题后,也许你可以指导我找到正确的路径 考虑以下代码: struct Foo { using Y = std::vector<std::string>; using X = std::vector<Y>; void add (Y y) {
std::move()
的问题。我知道SO不是一个问“你的意见是什么”(类模板Boo
)这类问题的好地方,但在这里,我想确定我的理解是否正确,在你阅读这个问题后,也许你可以指导我找到正确的路径
考虑以下代码:
struct Foo {
using Y = std::vector<std::string>;
using X = std::vector<Y>;
void add (Y y) {
src.push_back (std::move (y)); // (1)
src = process (std::move (src)); // (2)
}
private:
X process (X&& vec) { // (F)
for (auto& v : vec) {
v.resize (10); // (3)
}
return std::move (vec);
}
X src;
};
?
因此,如果Foo::src
有大量元素,那么
担保与较低的效率相关(因为必须制作额外的副本)
也许保证级别应该由类的用户决定,将其设置为类模板,如下所示:
struct S {};
struct B {};
template <typename T>
struct Boo {
using Y = std::vector<std::string>;
using X = std::vector<Y>;
void add (Y y) {
src.push_back (std::move (y));
src = process_helper (typename std::is_same<T, S>::type {});
}
private:
X process_helper (std::true_type) {
return process (src);
}
X process_helper (std::false_type) {
return process (std::move (src));
}
X process (X vec) {
for (auto& v : vec) {
v.resize (10);
}
return std::move (vec);
}
X src;
};
struct S{};
结构B{};
模板
结构Boo{
使用Y=std::vector;
使用X=std::vector;
无效添加(Y){
src.push_back(标准::移动(y));
src=process\u helper(typename std::is\u same::type{});
}
私人:
X进程\u助手(标准::真\u类型){
返回过程(src);
}
X进程\u助手(标准::假\u类型){
返回过程(std::move(src));
}
X过程(X向量){
用于(自动&v:vec){
v、 调整大小(10);
}
返回标准::移动(vec);
}
X src;
};
这是个好主意还是坏主意?
process
间接地做src=std::move(src)
@nwp:我不这么认为:它首先移动构造一个临时的。为什么不X进程(X&&vec_-in){auto vec=std::move(vec_-in);
,或者干脆X进程(X-vec)
?啊,因为这个调用去掉了你的src。真的要修复它,你需要src.push_back(std::move(y));
在插入之前“处理”y
,或者跟踪如何反转所有内容(不使用异常检查来减少开销)?@Yakk我没有提到resize()背后的全部想法
调用,因为我认为它不值得,但是如果您建议在插入之前处理y
,我不得不担心您(或我),我不能这样做,因为我希望所有src
行的长度完全相同,这意味着如果我通过y
,其中有不同(更大)的行大小比src
中的任何行都大,然后我必须采取措施调整其余行的大小,以保持它们相等(等于y)。异常后恢复仍然是一种选择。就个人而言:只要您不是在编写通用库,我就会仔细查看调用代码,看看它是否需要强异常保证,并相应地决定是否使用一种变体。特别是,应用程序在r aStd::抛出错误的\u alloc。
struct S {};
struct B {};
template <typename T>
struct Boo {
using Y = std::vector<std::string>;
using X = std::vector<Y>;
void add (Y y) {
src.push_back (std::move (y));
src = process_helper (typename std::is_same<T, S>::type {});
}
private:
X process_helper (std::true_type) {
return process (src);
}
X process_helper (std::false_type) {
return process (std::move (src));
}
X process (X vec) {
for (auto& v : vec) {
v.resize (10);
}
return std::move (vec);
}
X src;
};