c++ 关于使用用户提供的副本的已弃用副本警告的问题

r1zhe5dt  于 2023-10-20  发布在  其他
关注(0)|答案(2)|浏览(132)

我尝试定义一个基于模板的vector类,但得到此警告消息

warning: definition of implicit copy constructor for 'Vec<double, 3>' is deprecated because it has a user-provided copy assignment operator [-Wdeprecated-copy-with-user-provided-copy]
        Vec &operator=(const Vec &t)
             ^
...test_temp.cpp:86:17: note: in implicit copy constructor for 'Vec<double, 3>' first required here
    auto vadd = v1 + v2;
                ^
1 warning generated.

我不知道这里有什么好的做法。我应该把赋值操作符标记为默认值,还是只添加-Wno-deprecated-copy-with-user-provided-copy?是否有其他解决方案来解决这个问题?
这是一个测试文件:

#include <iostream>
#include <assert.h>

    template <typename T, uint Size>
    class Vec
    {
    public:
        static const int NUM_COMPONENTS = Size;
        T Components[NUM_COMPONENTS];
        Vec() {}
        Vec(T init)
        {
            for (uint i = 0; i < this->NUM_COMPONENTS; i++)
            {
                this->Components[i] = init;
            }
        }

        Vec<T,Size> operator+(const Vec &t) const
        {
            assert(this->NUM_COMPONENTS == t.NUM_COMPONENTS);
            Vec<T,Size> result;
            for (uint i = 0; i < this->NUM_COMPONENTS; i++)
            {
                result[i] = this->Components[i] + t.Components[i];
            }
            return result;
        }

        Vec<T,Size> operator-(const Vec &t) const
        {
            assert(this->NUM_COMPONENTS == t.NUM_COMPONENTS);
            Vec<T,Size> result;
            for (uint i = 0; i < this->NUM_COMPONENTS; i++)
            {
                result[i] = this->Components[i] - t.Components[i];
            }
            return result;
        }

        T &operator[](uint index)
        {
            assert(index >= 0);
            assert(index < this->NUM_COMPONENTS);
            return this->Components[index];
        }
        
        const T &operator[](uint index) const
        {
            assert(index >= 0);
            assert(index < this->NUM_COMPONENTS);
            return this->Components[index];
        }

        Vec<T,Size> &operator=(const Vec<T,Size> &t)
        {
            assert(this->NUM_COMPONENTS == t.NUM_COMPONENTS);
            for (uint i = 0; i < this->NUM_COMPONENTS; i++)
            {
                this->Components[i] = t.Components[i];
            }
            return *this;
        }
        void Show()
        {
            for (int i = 0; i < this->NUM_COMPONENTS; i++)
            {
                printf("%lf ", 1.0 * this->Components[i]);
            }
            printf("\n");
        }
    };

int main() {
    Vec<double, 3> v1;
    for (int i = 0; i < 3; i++)
    {
        v1[i] = 2.0;
    }
    Vec<double, 3> v2;
    for (int i = 0; i < 3; i++)
    {
        v2[i] = 3.0;
    }
    auto vadd = v1 + v2;
    std::cout << "test";
    vadd.Show();
    return 0;
}

设置cmake flag为:

set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wpedantic")

非常感谢您的帮助!

3lxsmp7m

3lxsmp7m1#

你根本不应该声明复制赋值操作符。隐式定义的一个确实已经做了你想要的。
在以下情况下,始终遵循零法则:不要声明析构函数、复制/移动构造函数或复制/移动赋值运算符。如果你确实需要它们中的任何一个,那么就遵循三/五规则,并定义它们中的所有,因为如果是这样的话,你几乎肯定也需要它们中的自定义行为。
这是C++类设计中最重要的规则。不幸的是,语言本身并没有强制执行它。然而,当复制赋值运算符已经由用户声明时,复制构造函数的隐式声明已被弃用,以支持该规则。这就是编译器警告你的。
解决方案是 * 不 * 添加一个复制构造函数。将其定义为与编译器将生成的代码完全相同总是会导致更差的代码。

0s7z1bwu

0s7z1bwu2#

我刚刚发现添加一个复制构造函数(我忘记添加了)可以解决这个问题,只需在这里发布一个潜在的答案:

#include <iostream>
#include <assert.h>

template <typename T, uint Size>
class Vec
{
public:
    static const int NUM_COMPONENTS = Size;
    T Components[NUM_COMPONENTS];
    Vec() {}
    Vec(T init)
    {
        for (uint i = 0; i < this->NUM_COMPONENTS; i++)
        {
            this->Components[i] = init;
        }
    }

    Vec(const Vec &src)
    {
        assert(this->NUM_COMPONENTS == src.NUM_COMPONENTS);
        for (uint i = 0; i < Size; ++i)
        {
            this->Components[i] = src[i];
        }
    }

    Vec operator+(const Vec &t) const
    {
        assert(this->NUM_COMPONENTS == t.NUM_COMPONENTS);
        Vec<T, Size> result;
        for (uint i = 0; i < this->NUM_COMPONENTS; i++)
        {
            result[i] = this->Components[i] + t.Components[i];
        }
        return result;
    }

    Vec operator-(const Vec &t) const
    {
        assert(this->NUM_COMPONENTS == t.NUM_COMPONENTS);
        Vec<T, Size> result;
        for (uint i = 0; i < this->NUM_COMPONENTS; i++)
        {
            result[i] = this->Components[i] - t.Components[i];
        }
        return result;
    }

    T &operator[](int index)
    {
        assert(index >= 0);
        assert(index < this->NUM_COMPONENTS);
        return this->Components[index];
    }

    const T &operator[](int index) const
    {
        assert(index >= 0);
        assert(index < this->NUM_COMPONENTS);
        return this->Components[index];
    }

    Vec &operator=(const Vec &t)
    {
        assert(this->NUM_COMPONENTS == t.NUM_COMPONENTS);
        for (uint i = 0; i < this->NUM_COMPONENTS; i++)
        {
            this->Components[i] = t.Components[i];
        }
        return *this;
    }
    void Show()
    {
        for (int i = 0; i < this->NUM_COMPONENTS; i++)
        {
            printf("%lf ", 1.0 * this->Components[i]);
        }
        printf("\n");
    }
};

int main()
{
    Vec<double, 3> v1;
    for (int i = 0; i < 3; i++)
    {
        v1[i] = 2.0;
    }
    Vec<double, 3> v2;
    for (int i = 0; i < 3; i++)
    {
        v2[i] = 3.0;
    }
    auto vadd = v1 + v2;
    std::cout << "test";
    vadd.Show();
    return 0;
}

相关问题