c++ - MS C++ 与 Clang 中的 move 语义

标签 c++ visual-c++ clang visual-c++-2010 move-semantics

在使用我创建的数组类型对 move 语义进行了一些实验之后,我想知道为什么 Microsoft 的 C++ 编译器在按值从方法返回时调用 move 构造函数,而 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;
}

最佳答案

复制省略是罕见的优化之一,其中标准允许不同的可观察行为(它不属于假设规则),但不是未定义的行为。

在此上下文中是否调用或省略任何复制或 move 构造函数是未指定的,不同的编译器可能有不同的行为,但都是正确的。

关于c++ - MS C++ 与 Clang 中的 move 语义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9865675/

相关文章:

visual-c++ - Visual Studio 2012 update 3 编译器错误 - 不调用 dtor

compiler-construction - 从什么地方调用Compiler-RT?

c++11 - 在 Clang 中设置为默认 C++11

c++ - 在三个src文件中使用extern

c++ - C++中的结构属性继承

c++ - Clistctrl选择检测

c++ - clang-11 是否通过 -fcoroutines 标志调用 <coroutine> header ?

c++ - stdlib fopen 中的缓存如何工作?

c++11 模板工厂模式和带参数的构造函数

visual-c++ - 在 C++ 中比较两个 GUID 的相等性