【发布时间】:2012-04-09 13:49:10
【问题描述】:
在使用我创建的数组类型对移动语义进行了一些实验之后,我想知道为什么 Microsoft 的 C++ 编译器在从方法按值返回时调用移动构造函数,而 Clang 编译器将副本全部省略?
Clang 的这种行为是正确的还是不正确的?或 Microsoft 的正确行为?
#include <algorithm>
#include <iostream>
template<typename T>
class Array {
public:
template<typename E>
class ArrayIterator {
public:
ArrayIterator(Array<E>& elements, int index) : position_(index), elements_(elements) {
}
T& operator * () {
return elements_[position_];
}
ArrayIterator& operator++ () {
position_++;
return *this;
}
ArrayIterator operator++ (int) {
return ArrayIterator(elements_, ++position_);
}
bool operator != (ArrayIterator const & other) {
return position_ != other.position_;
}
private:
int position_;
Array<E>& elements_;
};
typedef ArrayIterator<T> iterator;
Array();
explicit Array(int size);
~Array();
Array(const Array& other);
Array(Array&& other);
Array<T>& operator = (Array other);
T& operator[](int index);
int size() const;
iterator begin();
iterator end();
private:
void internal_swap(Array& other);
T *elements_;
int length_;
};
template<typename T>
Array<T>::Array() {
length_ = 0;
elements_ = 0;
}
template<typename T>
Array<T>::Array(int size) {
elements_ = new T[size];
length_ = size;
}
template<typename T>
Array<T>::~Array() {
delete[] elements_;
std::cout << "Destroy...." << std::endl;
}
template<typename T>
Array<T>::Array(const Array<T>& other) {
std::cout << "copy ctor" << std::endl;
length_ = other.size();
T *elements = new T[size()];
std::copy(other.elements_, other.elements_ + other.size(), elements);
elements_ = elements;
}
template<typename T>
Array<T>::Array(Array<T>&& other) {
std::cout << "move ctor" << std::endl;
length_ = other.size();
T* oelements = other.elements_;
other.elements_ = 0;
this->elements_ = oelements;
}
template<typename T>
Array<T>& Array<T>::operator = (Array other) {
internal_swap(other);
return *this;
}
template<typename T>
T& Array<T>::operator[](int index) {
return elements_[index];
}
template<typename T>
int Array<T>::size() const {
return length_;
}
template<typename T>
typename Array<T>::iterator Array<T>::begin() {
return iterator(*this, 0);
}
template<typename T>
typename Array<T>::iterator Array<T>::end() {
return iterator(*this, size());
};
template<typename T>
void Array<T>::internal_swap(Array& other){
T* oelements = other.elements_;
other.elements_ = this->elements_;
this->elements_ = oelements;
}
Array<int> get_values(int x);
int main(int argc, const char *argv[]) {
Array<int> a = get_values(2);
for (Array<int>::iterator i = a.begin(); i != a.end(); ++i) {
std::cout << *i << std::endl;
}
return 0;
}
Array<int> get_values(int x) {
Array<int> a(10);
if(x == 1) return a;
for (int i = 0; i <= 9; i++) {
a[i] = 1 + i;
}
return a;
}
【问题讨论】:
-
MSVC 和 Clang 的编译器标志是什么?
-
XCode 4.3 和 VS 2010 的所有默认值。
-
是的,但是,VS 中的默认设置是调试模式,也就是没有优化......所以让我们说一下有点不同:你是否在发布模式下编译/启用了优化?
-
@Xeo:用 /O2(生成快速代码)和 /GL(整个程序优化)编译仍然输出“move ctor”...
-
请注意,如果您在
get_values()函数体中注释掉if(x == 1) return a;行,则应用 NRVO。似乎if语句阻止了 NRVO...
标签: c++ visual-c++ clang visual-c++-2010 move-semantics