应该std :: copy()或std :: move()的空范围是否需要有效的目的地?

Hug*_*ues 10 c++ visual-studio c++11

std::move(),因为它检测到在Visual Studio 2013(与调试配置)编译时在下面的代码发出警告,运行时dest是一个nullptr.但是,源范围是空的,因此dest永远不应该访问.C++标准可能不清楚是否允许这样做?它声明: 要求:结果不应在[first,last]范围内. A nullptr似乎满足了这个要求.

#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec;
    int* dest = nullptr;
    // The range [begin(vec),end(vec)) is empty, so dest should never be accessed.
    // However, it results in an assertion warning in VS2013.
    std::move(std::begin(vec), std::end(vec), dest);
}
Run Code Online (Sandbox Code Playgroud)

How*_*ant 15

不仅需要满足Requires:子句,还需要满足Effects:Returns:子句中的所有内容.我们来看看吧:

效果:在的范围内复制元件[first,last)为范围[result,result + (last - first))从开始first和前进到last.

因为first == last,范围[result, result + 0)必须是有效范围.

[iterator.requirements.general]/p7陈述:

范围[i,i)是空的范围; ... Range [i,j)当且仅当j可以从中获得时才有效i.

并且同一部分的p6说明:

迭代器j被称为从一个迭代可达i当且仅当存在的表达的应用程序的有限序列++i ,使i == j.

从这些段落中我得出结论:

int* dest = nullptr;
Run Code Online (Sandbox Code Playgroud)

然后[dest, dest)形成一个有效的空范围.因此,Effects:段落中的第一句对我来说没问题:

对于每个非负整数n < (last - first),执行*(result + n) = *(first + n).

没有非负整数n < 0,因此不能执行任何赋值.所以第二句不禁止dest == nullptr.

返回: result + (last - first).

[expr.add]/p8特别允许将0添加到任何指针值,结果比较等于原始指针值.因此dest + 0是一个等于的有效表达式nullptr.返回:子句没有问题.

要求: result不得在范围内[first,last).

我认为没有合理的解释方式dest可以"在"空的范围内.

复杂性:完全last - first分配.

这证实不能完成任务.

我在标准中找不到任何声明,使得这个例子不是格式良好的.