相关疑难解决方法(0)

移动赋值运算符和`if(this!=&rhs)`

在类的赋值运算符中,通常需要检查所分配的对象是否是调用对象,这样就不会搞砸了:

Class& Class::operator=(const Class& rhs) {
    if (this != &rhs) {
        // do the assignment
    }

    return *this;
}
Run Code Online (Sandbox Code Playgroud)

移动赋值运算符需要相同的东西吗?是否有过这样的情况this == &rhs

? Class::operator=(Class&& rhs) {
    ?
}
Run Code Online (Sandbox Code Playgroud)

c++ move-semantics c++11 move-assignment-operator

117
推荐指数
3
解决办法
4万
查看次数

从C++ std :: vector中删除第i项

如何从中删除第i项std::vector

我知道我想删除第i个元素.我int i; and std::vector<process> pList;在那里process是一个结构.我想做一些与以下相同的事情:

pList.remove(i);
Run Code Online (Sandbox Code Playgroud)

c++ vector

32
推荐指数
4
解决办法
6万
查看次数

std :: swap(x,x)是否保证x不变?

这个问题是基于Scott Meyers最近发表的博客文章.

看起来"显而易见" std::swap(x, x)应该x在C++ 98和C++ 11中保持不变,但我无法在任何标准中找到任何保证.C++ 98 std::swap在复制构造和复制赋值方面进行了定义,而C++ 11则根据移动构造和移动赋值来定义它,这似乎是相关的,因为在C++ 11(和C++ 14)中,17.6 .4.9表示移动分配不需要自我分配安全:

如果函数参数绑定到右值引用参数,则实现可以假定此参数是对此参数的唯一引用.... [注意:如果程序在将左值传递给库函数时将左值转换为x值(例如通过使用参数move(x)调用函数),程序实际上要求该函数将该左值视为暂时的.实现可以自由地优化别名检查,如果参数是左值,则可能需要这些检查. - 尾注]

引起这种措辞的缺陷报告使结果清晰:

这澄清了移动赋值运算符不需要执行复制赋值运算符中常见(并且需要)的传统if(this!=&rhs)测试.

但是在C++ 11和C++ 14中,std::swap预计会使用这个实现,

template<typename T>
void swap(T& lhs, T& rhs)
{
  auto temp(std::move(lhs));
  lhs = std::move(rhs);
  rhs = std::move(temp); 
}
Run Code Online (Sandbox Code Playgroud)

并且第一个赋值是对self进行赋值,其中参数是rvalue.如果移动赋值运算符T遵循标准库的策略并且不担心赋值给自己,那么这似乎可以判断未定义的行为,这也意味着它std::swap(x, x)也会具有UB.

即使是孤立的,这也是令人担忧的,但是如果我们认为std::swap(x, x)在C++ 98中应该是安全的,那么这也意味着C++ std::swap11/14可以默默地破坏C++ 98代码.

所以std::swap(x, x)保证x保持不变?在C++ 98中?在C++ 11中?如果是,那么它如何与17.6.4.9的移动分配许可相互作用而不是自我分配安全的?

c++ swap c++11

24
推荐指数
1
解决办法
1568
查看次数

在移动赋值和移动构造函数方面实现std :: swap

以下是可能的定义std::swap:

template<class T>
void swap(T& a, T& b) {
  T tmp(std::move(a));
  a = std::move(b);
  b = std::move(tmp);
}
Run Code Online (Sandbox Code Playgroud)

我相信

  1. std::swap(v,v) 保证没有效果
  2. std::swap 可以如上实现.

以下引用似乎暗示这些信念是矛盾的.

17.6.4.9函数参数[res.on.arguments]

1除非另有明确说明,否则以下各项均适用于C++标准库中定义的函数的所有参数.

...

  • 如果函数参数绑定到右值引用参数,则实现可以假定此参数是对此参数的唯一引用.[注意:如果参数是T &&形式的通用参数并且绑定了类型A的左值,则参数绑定到左值引用(14.8.2.1),因此不包含在前一句中. - 结束注释] [注意:如果程序在将左值传递给库函数时将左值转换为x值(例如通过使用参数move(x)调用函数),程序实际上会要求该函数处理该左值作为临时的.实现可以自由地优化别名检查,如果参数是左值,则可能需要这些检查.-endnote]

(感谢霍华德Hinnant(欣南特)用于提供报价)

让我们v从标准模板库中获取一些可移动类型的对象并考虑该调用std::swap(v, v).在该行a = std::move(b);以上,这是内部的情况T::operator=(T&& t)的是this == &b,这样的参数是唯一的参考.这违反了上面的要求,因此该行在a = std::move(b)调用时调用未定义的行为std::swap(v, v).

这里有什么解释?

c++ stl move-semantics c++11

10
推荐指数
2
解决办法
2030
查看次数

移动分配给自己的行为

示例代码:

#include <iostream>

int main()
{   
    std::vector<int> w(20, 123), x;
    w = std::move(w);
    std::cout << w.size() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

g ++ 4.8.3上的输出: 0

当然,标准说移动赋值运算符使操作数处于未指定状态.例如,如果代码是x = std::move(w);那么我们期望w.size()为零.

但是,是否有指定的排序或其他条款涵盖自动案件?是否未指定大小是否为020其他内容或未定义的行为?标准容器在这里有任何定义的语义吗?

相关:此线程讨论您是否应该关心自己的类中的自动移动,但不讨论标准容器的移动赋值运算符是否执行,并且不提供标准引用.

NB.这与功能完全相同w = static_cast< std::vector<int> && >(w);std::move不同吗?

c++ move-semantics

8
推荐指数
1
解决办法
1689
查看次数

移动使用无效?

有人可以给我提示为什么这段代码没有输出任何东西?我假设它与移动线有关...

#include <iostream> 
#include <vector> 
#include <algorithm> 

using namespace std; 

int main(){ 
vector<int> v{66,79,154,24,76,13,7}; 

v = move(v); 
for(auto i: v) 
cout << i << " "; 
}
Run Code Online (Sandbox Code Playgroud)

更新:所以我添加了系统("暂停"); 帮助自己.我是否需要它并不是我所关注的.当我在Visual Studio 2013中再次运行代码时,它工作正常.但是,当我使用C++ 14运行Ideone时,它没有输出任何内容.现在有点困惑.

Visual Studio 2013 Ideone

c++ move vector visual-studio

6
推荐指数
1
解决办法
167
查看次数

创建一个rvalue并通过转发将其传递给一个函数

我有这个代码似乎工作,但我不确定我是否只是看到未定义的行为或它实际上工作.

#include <string>
#include <vector>
#include <sstream>
#include <numeric>
#include <iostream>

auto main() -> int {

    const std::vector<std::string> keywords = {
        "and","and_eq","asm","auto","bitand", "bitor","bool","break","case",
        "catch","char","class","compl","const", "const_cast","continue",
        "default","#define","delete","do","double","dynamic_cast","else","enum",
        "explicit","export","extern", "extern \"C\"","false","float",
        "for","friend","goto","if","inline","int","long","mutable","namespace",
        "new","not","not_eq","operator","or", "or_eq","private","protected",
        "public","register","reinterpret_cast","short","signed","sizeof",
        "static","static_cast","struct","switch","template","this","throw",
        "true","try","typedef","typeid","typename","union","unsigned","using",
        "virtual","void","volatile","void","wchar_t","while","xor","xor_eq",
        "return", "decltype"
    };

    std::ostringstream keywords_pattern =
        std::accumulate(keywords.begin(), keywords.end(), std::forward<std::ostringstream>(
            std::ostringstream("constexpr", std::ostringstream::ate)),
            [](std::ostringstream &accum, const std::string& next) -> std::ostringstream&& {
                accum << '|' << next;
                return std::forward<std::ostringstream>(std::move(accum));
            });

    std::cout << keywords_pattern.str() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

它能做什么:

所有这一切都是将C++关键字的向量组合成一个分隔的字符串|.

输出:

这是我运行时的输出:

 onstexpr|and|and_eq|asm|auto|bitand|bitor|bool|break|case|catch|char|class|compl|const|const_cast|continue|default|#define|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|extern "C"|false|float|for|friend|goto|if|inline|int|long|mutable|namespace|new|not|not_eq|operator|or|or_eq|private|protected|public|register|reinterpret_cast|short|signed|sizeof|static|static_cast|struct|switch|template|this|throw|true|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|void|wchar_t|while|xor|xor_eq|return|decltype
Run Code Online (Sandbox Code Playgroud)

不, …

c++ debugging reference c++11

1
推荐指数
1
解决办法
67
查看次数