一位同事编写了以下代码,我确信这是错误的.
我想向他解释问题,但不知道正确的术语,所以我找不到支持我的立场的参考资料:
他的代码:
BSTR someString = _bstr_t(L"Hello World");
Run Code Online (Sandbox Code Playgroud)
为什么我认为它是错误的:
我相信它会_bstr_t(L"Hello World");调用构造函数_bstr_t,并创建一个该类型的短期临时变量.在该行代码之后(在分号序列点之后),该临时符将被自动删除,并且其字符串空间被释放.
这将someString指向已释放的内存.
问题:
构造函数调用的正确术语是什么?
你能指出一些描述使用细节的参考/术语/页面吗?
临时_bstr_t对象有术语吗?
我想我会称之为"匿名,临时变量",但我不知道这在技术上是否准确.
(或者在我的分析中我可能完全错了......如果是的话,我很想知道)
为了澄清:
_bstr_t是一个C++类,Microsoft通常用它来包装它们的BSTR类型,所以它有构造函数/析构函数/运算符等.
BSTR是一个只有a的typedef WCHAR*,所以它没有任何逻辑.它只是一个愚蠢的指针.
我是编程新手.对不起,我的英语不好.我试图使用rvalue作为初始对象的初始化器.因此,根据代码,它将打印出使用的构造函数和赋值运算符.但结果是对象"what2"和"what3",那些不打印任何东西.这是代码:
#include <iostream>
using namespace std;
class X{
public:
int x;
X()= default;
X(int num):x{num}{}
X(const X& y){
x = y.x;
std::cout << "copy constructor" << std::endl;
std::cout << x << std::endl;
}
X& operator=(const X& d){
x = d.x;
std::cout << "copy assignment" << std::endl;
return *this;
}
X(X&& y){
x = y.x;
std::cout << "move constructor" << std::endl;
}
X& operator=(X&& b){
x = b.x;
std::cout << "move assignment" << std::endl;
return *this;
}
};
X operator +(const …Run Code Online (Sandbox Code Playgroud) 假设T是一个C++类,如果我这样做T a = b;,是复制构造函数还是赋值运算符?
我当前的实验显示复制构造函数被调用,但不明白为什么.
#include <iostream>
using namespace std;
class T {
public:
// Default constructor.
T() : x("Default constructor") { }
// Copy constructor.
T(const T&) : x("Copy constructor") { }
// Assignment operator.
T& operator=(const T&) { x = "Assignment operator"; }
string x;
};
int main() {
T a;
T b = a;
cout << "T b = a; " << b.x << "\n";
b = a;
cout << "b = a; …Run Code Online (Sandbox Code Playgroud) 如果我在 C++11 中保持对函数的非引用返回值的常量引用,那么堆栈中的引用点在哪里?这样做安全吗?
string foo() {
std::string foo_ret = "foo string";
return foo_ret;
}
int main() {
const std::string& a = foo();
}
Run Code Online (Sandbox Code Playgroud) 我正在学习C++ 11中的移动语义.我写了一个小程序来测试移动语义的行为.但它没有像我预期的那样表现,有人能解释我为什么吗?
#include<iostream>
using namespace std;
class Vector
{
public:
Vector()
{
cout << "empty Ctor"<<endl;
array = new int[10];
size = 10;
}
Vector(int n)
{
array = new int[n];
size = n;
for (int i=0; i<size; ++i)
array[i] = i;
cout << "Ctor"<<endl;
}
Vector(const Vector& v):size(v.size)
{
array = new int[size];
for (int i=0; i<size; ++i)
array[i] = v.array[i];
cout << "copy"<<endl;
}
Vector(Vector&& v):size(v.size)
{
array = v.array;
v.array = nullptr;
cout << "move"<<endl;
}
~Vector() …Run Code Online (Sandbox Code Playgroud) 我想在现代C++中实现构建器模式.来自Java背景,这是我想要模仿的东西:
// Usage
FooBuilder builder;
builder.setArg1(a);
builder.setArg2(b);
Foo foo = builder.build();
// Implementation
public class FooBuilder {
// ...
public Foo build() {
return new Foo(a, b);
}
}
Run Code Online (Sandbox Code Playgroud)
典型的旧教科书只是建议一个人在C++中这样做:
class FooBuilder {
// ...
Foo* build() {
return new Foo(m_a, m_b);
}
}
Run Code Online (Sandbox Code Playgroud)
这显然不是一个好主意,因为处理原始指针可能容易出错.到目前为止我提出的最好的是std::unique_ptr手动使用:
class FooBuilder {
// ...
std::unique_ptr<Foo> build() {
return std::make_unique<Foo>(m_a, m_b);
}
}
// Usage
auto fooPtr = builder.build();
Foo& foo = *fooPtr;
foo.someMethod();
Run Code Online (Sandbox Code Playgroud)
它更好,因为它不需要手动delete,这个双线程转换为参考是丑陋的,更重要的是,它使用堆分配,而简单的无构建器版本只需一个简单的堆栈分配就完全没问题:
Foo foo(..., ...); // <= on …Run Code Online (Sandbox Code Playgroud) 类的移动构造函数接受可以引用临时对象的rvalue引用.所以,我有临时对象和适当的移动构造函数,它可以接受对临时对象的引用,但是移动构造函数不会被调用.怎么了?
//g++ 5.4.0
#include <iostream>
class foo
{
int data;
public:
foo(int v) : data(v) {std::cout << "foo(int)\n";}
foo(foo&& f)
{
std::cout << "moved\n";
}
void print()
{
std::cout << data;
}
};
void acceptTmp(foo f)
{
f.print();
}
int main()
{
foo f1 = foo(100);
f1.print();
acceptTmp(foo(200)); //also does not move
}
Run Code Online (Sandbox Code Playgroud) 今天,我遇到了一些我对复制构造函数不太了解的内容。
考虑下面的代码:
#include <iostream>
using namespace std;
class some_class {
public:
some_class() {
}
some_class(const some_class&) {
cout << "copy!" << endl;
}
some_class call() {
cout << "is called" << endl;
return *this; // <-- should call the copy constructor
}
};
some_class create() {
return some_class();
}
static some_class origin;
static some_class copy = origin; // <-- should call the copy constructor
int main(void)
{
return 0;
}
Run Code Online (Sandbox Code Playgroud)
然后在将原点分配给副本时调用副本构造函数,这很有意义。但是,如果我将复制声明更改为
static some_class copy = some_class();
Run Code Online (Sandbox Code Playgroud)
它没有被调用。即使在使用该create()函数时,它也不会调用复制构造函数。但是,将其更改为
static …Run Code Online (Sandbox Code Playgroud) std::unique_ptr由于复制省略,我能够将右值作为参数传递给如下所示的函数。副本是否一定会被C ++ 11标准淘汰,或者在某些实现中无法编译?
void take_unique_ptr_by_value(std::unique_ptr<int> sp) {
cout << "Value is " << *sp.get() << std::endl;
}
// I am able to call the function above like this:
take_unique_ptr_by_value(std::make_unique<int>(3));
Run Code Online (Sandbox Code Playgroud) 我有以下代码:
#include <iostream>
using namespace std;
struct A
{
A() {}
A(const A&) { cout << "copy const" << endl; }
A(A&) { cout << "copy non const" << endl; }
};
A f(A a)
{
return a;
}
int main() {
A a1 = f(A());
}
Run Code Online (Sandbox Code Playgroud)
该A(A&)拷贝构造函数被调用。为什么A(const A&)不调用,因为我传递了一个临时对象?当我注释掉A(const A&)复制构造函数时,程序不会编译。
c++ ×10
c++11 ×4
copy-elision ×2
bstr ×1
builder ×1
com ×1
constructor ×1
reference ×1
return-value ×1