c++ - 如何避免在 C++11 中触发这种复制构造函数?

标签 c++ c++11 c++17

我想在函数中创建一个对象并在外部使用它。

我在c++17标准下写了下面的代码,好像还可以。

#include <iostream>

struct Vector2 {
    Vector2() = default;
    Vector2(int x, int y) : x(x), y(y) {}
    Vector2(const Vector2 &) = delete;
    Vector2 &operator=(const Vector2 &) = delete;

    int x = 0;
    int y = 0;
};

Vector2 newVec(int x, int y) {
    return Vector2(x, y);
}

int main() {
    auto v = newVec(1, 2);
    std::cout << v.x * v.y << std::endl;
    return 0;
}

但是当我切换到c++11标准时,我无法编译它。

note: 'Vector2' has been explicitly marked deleted here Vector2(const Vector2 &) = delete;

我想我在 newVec 函数中构造了一个临时的 Vector2 对象。返回时,Vector2 以临时变量作为参数调用复制构造函数。但是我把拷贝构造函数标记为'delete',所以编译不了。

我的问题是 C++11 标准下的等效代码是什么? c++17 做了什么来避免这个拷贝构造函数?

最佳答案

What did c++17 do to avoid this copy constructor?

这个:

auto v = newVec(1, 2);

是一种名为“保证复制省略”的语言功能的激励案例之一。来自 that paper 的示例:

auto x = make(); // error, can't perform the move you didn't want,
                 // even though compiler would not actually call it

在 C++17 之前,该表达式总是复制初始化。我们用 auto 推导出类型,这给了我们 Vector2 ,然后我们试图构建一个 Vector2来自 Vector2 类型的右值.这是通常的过程——枚举构造函数等。最匹配的是你的复制构造函数,它被删除了,因此整个过程是错误的。

悲伤的脸。

在 C++17 中,这是完全不同的。从相同类型的纯右值初始化根本不会尝试找到构造函数。没有复制或移动。它只是给你一个 Vector2那就是 newVec(1, 2) 的值, directly .这就是这里的变化 - 不是在 C++17 中复制初始化有效,更重要的是它甚至不再是同一种初始化。


My question is what is the equivalent code under the C++11 standard?

根本没有办法像这样构造一个不可移动的物体。来自同一篇论文:

struct NonMoveable { /* ... */ };
NonMoveable make() { /* how to make this work without a copy? */ }

如果你想要像 make() 这样的函数(在您的示例中为 newVec())要工作,类型必须至少是可移动的。这意味着:

  • 添加移动构造函数
  • 取消删除你的复制构造函数
  • 如果以上都不可能,把它放在堆上——用类似unique_ptr<Vector2>的东西包装它, 这是可移动的

或者你传入make()您的对象并让函数在内部填充它:

void make(NonMoveable&);

这最终会降低可组合性,但它确实有效。如所写,它要求您的类型是默认可构造的,但也有解决方法。

关于c++ - 如何避免在 C++11 中触发这种复制构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55652169/

相关文章:

c++ - C++中的访问冲突

c++ - std::is_trivially_copyable 要求

c++ - 使用 lambda 作为 GLFWkeyfun

c++ - 使用位集适配器从operator []返回引用

c++ - 从2个模板类继承 `sameFunctionName<T>()` ==>不明确

c++ - C++17 中的数组赋值

c++ - 寻找球形纹理贴图的 theta 和 phi

c++ - QSignalMapper 是如何工作的?

c++11 - 在移动构造函数中使用 std::move

c++ - 将包含 std::thread 的类添加到 vector 中