C++11中unique_ptr的使用

2023-05-16

在C++中,动态内存的管理是通过一对运算符来完成的:new,在动态内存中为对象分配空间并返回一个指向该对象的指针,可以选择对对象进行初始化;delete,接受一个动态对象的指针,销毁该对象,并释放与之关联的内存。

动态内存的使用很容易出问题,因为确保在正确的时间释放内存是极其困难的。有时会忘记释放内存,在这种情况下会产生内存泄露;有时在尚有指针引用内存的情况下就释放了它,在这种情况下就会产生引用非法内存的指针。

为了更容易(同时也更安全)地使用动态内存,C++11标准库提供了两种智能指针(smart pointer)类型来管理动态对象。智能指针的行为类似常规指针,重要的区别是它负责自动释放所指的对象。C++11标准库提供的这两种智能指针的区别在于管理底层指针的方式:shared_ptr允许多个指针指向同一个对象;unique_ptr则"独占"所指向的对象。C++11标准库还定义了一个名为weak_ptr的辅助类,它是一种弱引用,指向shared_ptr所管理的对象。这三种类型都定义在memory头文件中。智能指针是模板类而不是指针。类似vector,智能指针也是模板,当创建一个智能指针时,必须提供额外的信息即指针可以指向的类型。默认初始化的智能指针中保存着一个空指针。智能指针的使用方式与普通指针类似。解引用一个智能指针返回它指向的对象。如果在一个条件判断中使用智能指针,效果就是检测它是否为空。

In C++, a smart pointer is implemented as a template class that mimics, by means of operator overloading, the behaviors of a traditional (raw) pointer, (e.g. dereferencing, assignment) while providing additional memory management features.

std::unique_ptr is a smart pointer that retains sole ownership of an object through a pointer and destroys that object when the unique_ptr goes out of scope. No two unique_ptr instances can manage the same object.

The object is destroyed and its memory deallocated when either of the following happens: (1)、the managing unique_ptr object is destroyed; (2)、the managing unique_ptr object is assigned another pointer via operator= or reset().

A unique_ptr may alternatively own no object, in which case it is called empty.

Only non-const unique_ptr can transfer the ownership of the managed object to another unique_ptr. The lifetime of an object managed by const std::unique_ptr is limited to the scope in which the pointer was created.

std::unique_ptr may be constructed for an incomplete type T. Conversely, std::shared_ptr can't be constructed from a raw pointer to incomplete type, but can be destroyed where T is incomplete.

A unique_ptr does not share its pointer. It cannot be copied to another unique_ptr, passed by value to a function, or used in any Standard Template Library (STL) algorithm that requires copies to be made. A unique_ptr can only be moved. This means that the ownership of the memory resource is transferred to another unique_ptr and the original unique_ptr no longer owns it.

When using unique_ptr, there can be at most one unique_ptr pointing at any one resource.When that unique_ptr is destroyed, the resource is automatically reclaimed.Because there can only be one unique_ptr to any resource, any attempt to make a copy of a unique_ptr will cause a compile-time error. However, unique_ptr can be moved using the new move semantics.

shared_ptr, allows for multiple pointers to point at a given resource. When the very last shared_ptr to a resource is destroyed, the resource will be deallocated. shared_ptr uses reference counting to track how many pointers refer to a resource, so you need to be careful not to introduce any reference cycles.

A unique_ptr is a container for a raw pointer, which the unique_ptr is said to own. A unique_ptr explicitly prevents copying of its contained pointer (as would happen with normal assignment), but the std::move function can be used to transfer ownership of the contained pointer to another unique_ptr. A unique_ptr cannot be copied because its copy constructor and assignment operators are explicitly deleted.

everything you can do with auto_ptr, unique_ptr will do as well.

There are two kinds of unique_ptr, one for scalars (i.e. non-arrays) and one for arrays:

(1)、unique_ptr<double> can hold a scalar of type double;

(2)、unique_ptr<double[]> can hold an array of double values with an unknown number of elements.

std::unique_ptr是C++11标准中用来取代std::auto_ptr的指针容器(在C++11中,auto_ptr被废弃)。它不能与其它unique_ptr类型的指针对象共享所指对象的内存。这种”所有权”仅能够通过标准库的move函数来转移。unique_ptr是一个删除了拷贝构造函数、保留了移动构造函数的指针封装类型。

一个unique_ptr"拥有"它所指向的对象。与shared_ptr不同,某个时刻只能有一个unique_ptr指向一个给定对象。当unique_ptr被销毁时,它所指向的对象也被销毁。与shared_ptr不同,在C++11中,没有类似make_shared的标准库函数返回一个unique_ptr。当定义一个unique_ptr时,需要将其绑定到一个new返回的指针上。类似shared_ptr,初始化unique_ptr必须采用直接初始化形式。由于一个unique_ptr拥有它指向的对象,因此unique_ptr不支持普通的拷贝或赋值操作。虽然不能拷贝或赋值unique_ptr,但可以通过调用release或reset将指针的所有权从一个(非const)unique_ptr转移给另一个unique。

调用release会切断unique_ptr和它原来管理的对象间的联系。release返回的指针通过被用来初始化另一个智能指针或给另一个智能指针赋值。如果不用另一个智能指针来保存release返回的指针,程序就要负责资源的释放。

不能拷贝unique_ptr的规则有一个例外:我们可以拷贝或赋值一个将要被销毁的unique_ptr,最常见的例子是从函数返回一个unique_ptr。

类似shared_ptr,unique_ptr默认情况下用delete释放它指向的对象。与shared_ptr一样,可以重载一个unique_ptr中默认的删除器。但是,unique_ptr管理删除器的方式与shared_ptr不同。

下图列出了unique_ptr支持的操作(来源于C++ Primer Fifth Edition 中文版):

下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:

#include "unique_ptr.hpp"
#include <iostream>
#include <memory>
#include <string>
#include <cstdlib>
#include <utility>
#include <vector>
#include <algorithm>
#include <cassert>
#include <fstream>
#include <functional>

namespace unique_ptr_ {

///
// reference: http://en.cppreference.com/w/cpp/memory/unique_ptr
struct Foo
{
	Foo()      { std::cout << "Foo::Foo\n"; }
	~Foo()     { std::cout << "Foo::~Foo\n"; }
	void bar() { std::cout << "Foo::bar\n"; }
};

void f(const Foo &)
{
	std::cout << "f(const Foo&)\n";
}

int test_unique_ptr1()
{
	std::unique_ptr<Foo> p1(new Foo);  // p1 owns Foo
	if (p1) p1->bar();

	{
		std::unique_ptr<Foo> p2(std::move(p1));  // now p2 owns Foo
		f(*p2);

		p1 = std::move(p2);  // ownership returns to p1
		std::cout << "destroying p2...\n";
	}

	if (p1) p1->bar();

	// Foo instance is destroyed when p1 goes out of scope

	return 0;
}

//
// reference: http://www.cplusplus.com/reference/memory/unique_ptr/unique_ptr/
int test_unique_ptr2()
{
	std::default_delete<int> d;
	std::unique_ptr<int> u1;
	std::unique_ptr<int> u2(nullptr);
	std::unique_ptr<int> u3(new int);
	std::unique_ptr<int> u4(new int, d);
	std::unique_ptr<int> u5(new int, std::default_delete<int>());
	std::unique_ptr<int> u6(std::move(u5));
	std::unique_ptr<int> u7(std::move(u6));
	std::unique_ptr<int> u8(std::auto_ptr<int>(new int));

	std::cout << "u1: " << (u1 ? "not null" : "null") << '\n';
	std::cout << "u2: " << (u2 ? "not null" : "null") << '\n';
	std::cout << "u3: " << (u3 ? "not null" : "null") << '\n';
	std::cout << "u4: " << (u4 ? "not null" : "null") << '\n';
	std::cout << "u5: " << (u5 ? "not null" : "null") << '\n';
	std::cout << "u6: " << (u6 ? "not null" : "null") << '\n';
	std::cout << "u7: " << (u7 ? "not null" : "null") << '\n';
	std::cout << "u8: " << (u8 ? "not null" : "null") << '\n';

	return 0;
}

//
// reference: http://eli.thegreenplace.net/2012/06/20/c11-using-unique_ptr-with-standard-library-containers
struct Foo_0 {
	Foo_0() { std::cerr << "Foo_0 [" << this << "] constructed\n"; }
	virtual ~Foo_0() { std::cerr << "Foo_0 [" << this << "] destructed\n"; }
};

void sink(std::unique_ptr<Foo_0> p) {
	std::cerr << "Sink owns Foo_0 [" << p.get() << "]\n";
}

std::unique_ptr<Foo_0> source() {
	std::cerr << "Creating Foo_0 in source\n";
	return std::unique_ptr<Foo_0>(new Foo_0);
}

int test_unique_ptr3()
{
	std::cerr << "Calling source\n";
	std::unique_ptr<Foo_0> pmain = source();  // Can also be written as
	// auto pmain = source();

	std::cerr << "Now pmain owns Foo [" << pmain.get() << "]\n";
	std::cerr << "Passing it to sink\n";
	// sink(pmain);                    // ERROR! can't copy unique_ptr
	sink(move(pmain));              // OK: can move it!

	std::cerr << "Main done\n";
	return 0;
}


// reference: http://www.codeguru.com/cpp/article.php/c17775/The-Smart-Pointer-That-Makes-Your-C-Applications-Safer--stduniqueptr.htm
void func(int*)
{

}

int test_unique_ptr4()
{
	// default construction
	std::unique_ptr<int> up; //creates an empty object

	// initialize with an argument
	std::unique_ptr<int> uptr(new int(3));
	double *pd = new double;
	std::unique_ptr<double> uptr2(pd);
	// overloaded * and ->
	*uptr2 = 23.5;
	std::unique_ptr<std::string> ups(new std::string("hello"));
	int len = ups->size();

	// Reset() releases the owned resource and optionally acquires a new resource:
	uptr2.reset(new double); //delete pd and acquire a new pointer
	uptr2.reset(); //delete the pointer acquired by the previous reset() call

	// If you need to access the owned pointer directly use get()
	func(uptr.get());

	// Unique_ptr has implicit conversion to bool.
	// This lets you use unique_ptr object in Boolean expressions such as this:
	if (ups) //implicit conversion to bool
		std::cout << *ups << std::endl;
	else
		std::cout << "an empty smart pointer" << std::endl;

	// Array Support: Unique_ptr can store arrays as well.
	// A unique_ptr that owns an array defines an overloaded operator [].
	// Obviously, the * and -> operators are not available.
	// Additionally, the default deleter calls delete[] instead of delete:
	std::unique_ptr<int[]> arrup(new int[5]);
	arrup[0] = 5;
	// std::cout << *arrup << std::endl; //error, operator * not defined 

	// Compatibility with Containers and Algorithms
	// You can safely store unique_ptr in Standard Library containers and let algorithms manipulate sequences of unique_ptr objects.
	std::vector<std::unique_ptr<int>> vi;
	vi.push_back(std::unique_ptr<int>(new int(0)));  // populate vector
	vi.push_back(std::unique_ptr<int>(new int(3)));
	vi.push_back(std::unique_ptr<int>(new int(2)));
	std::sort(vi.begin(), vi.end());  // result: {0, 2, 3}

	return 0;
}

//
template <typename T>
class Add {
public:
	T add_sub(T a, T b)
	{
		return (a + b) * (a - b);
	}
};


int test_unique_ptr5()
{
	std::unique_ptr<Add<int>> tt(new Add<int>());
	int a{ 10 }, b{ 5 };

	std::cout << tt->add_sub(a, b) << std::endl;

	return 0;
}

//
int test_unique_ptr6()
{
	std::unique_ptr<int[]> tmp(new int[100]);
	std::for_each(tmp.get(), tmp.get() + 100, [](int& n) {n = 66; });
	std::cout << tmp[99] << std::endl;

	return 0;
}

///
// reference: https://en.cppreference.com/w/cpp/memory/unique_ptr
struct B {
	virtual void bar() { std::cout << "B::bar\n"; }
	virtual ~B() = default;
};
struct D : B
{
	D() { std::cout << "D::D\n"; }
	~D() { std::cout << "D::~D\n"; }
	void bar() override { std::cout << "D::bar\n"; }
};

// a function consuming a unique_ptr can take it by value or by rvalue reference
std::unique_ptr<D> pass_through(std::unique_ptr<D> p)
{
	p->bar();
	return p;
}

void close_file(std::FILE* fp) { std::fclose(fp); }

int test_unique_ptr7()
{
	std::cout << "unique ownership semantics demo\n";
	{
		auto p = std::make_unique<D>(); // p is a unique_ptr that owns a D
		auto q = pass_through(std::move(p));
		assert(!p); // now p owns nothing and holds a null pointer
		q->bar();   // and q owns the D object
	} // ~D called here

	std::cout << "Runtime polymorphism demo\n";
	{
		std::unique_ptr<B> p = std::make_unique<D>(); // p is a unique_ptr that owns a D
		// as a pointer to base
		p->bar(); // virtual dispatch

		std::vector<std::unique_ptr<B>> v;  // unique_ptr can be stored in a container
		v.push_back(std::make_unique<D>());
		v.push_back(std::move(p));
		v.emplace_back(new D);
		for (auto& p : v) p->bar(); // virtual dispatch
	} // ~D called 3 times

	std::cout << "Custom deleter demo\n";
	std::ofstream("demo.txt") << 'x'; // prepare the file to read
	{
		std::unique_ptr<std::FILE, decltype(&close_file)> fp(std::fopen("demo.txt", "r"), &close_file);
		if (fp) // fopen could have failed; in which case fp holds a null pointer
			std::cout << (char)std::fgetc(fp.get()) << '\n';
	} // fclose() called here, but only if FILE* is not a null pointer
	// (that is, if fopen succeeded)

	std::cout << "Custom lambda-expression deleter demo\n";
	{
		std::unique_ptr<D, std::function<void(D*)>> p(new D, [](D* ptr)
		{
			std::cout << "destroying from a custom deleter...\n";
			delete ptr;
		});  // p owns D
		p->bar();
	} // the lambda above is called and D is destroyed

	std::cout << "Array form of unique_ptr demo\n";
	{
		std::unique_ptr<D[]> p{ new D[3] };
	} // calls ~D 3 times

	return 0;
}

/
// reference: http://www.cplusplus.com/reference/memory/unique_ptr/~unique_ptr/
int test_unique_ptr8()
{
	auto deleter = [](int*p){
		delete p;
		std::cout << "[deleter called]\n";
	};

	std::unique_ptr<int, decltype(deleter)> foo(new int, deleter);

	std::cout << "foo " << (foo ? "is not" : "is") << " empty\n";

	return 0;                        // [deleter called]
}

/
// reference: http://www.cplusplus.com/reference/memory/unique_ptr/get_deleter/
class state_deleter {  // a deleter class with state
	int count_;
public:
	state_deleter() : count_(0) {}
	template <class T>
	void operator()(T* p) {
		std::cout << "[deleted #" << ++count_ << "]\n";
		delete p;
	}
};

int test_unique_ptr9()
{
	state_deleter del;

	std::unique_ptr<int> p;   // uses default deleter

	// alpha and beta use independent copies of the deleter:
	std::unique_ptr<int, state_deleter> alpha(new int);
	std::unique_ptr<int, state_deleter> beta(new int, alpha.get_deleter());

	// gamma and delta share the deleter "del" (deleter type is a reference!):
	std::unique_ptr<int, state_deleter&> gamma(new int, del);
	std::unique_ptr<int, state_deleter&> delta(new int, gamma.get_deleter());

	std::cout << "resetting alpha..."; alpha.reset(new int);
	std::cout << "resetting beta..."; beta.reset(new int);
	std::cout << "resetting gamma..."; gamma.reset(new int);
	std::cout << "resetting delta..."; delta.reset(new int);

	std::cout << "calling gamma/delta deleter...";
	gamma.get_deleter()(new int);

	alpha.get_deleter() = state_deleter();  // a brand new deleter for alpha

	// additional deletions when unique_ptr objects reach out of scope
	// (in inverse order of declaration)

	return 0;
}

//
// reference: http://www.cplusplus.com/reference/memory/unique_ptr/operator=/
int test_unique_ptr10()
{
	std::unique_ptr<int> foo;
	std::unique_ptr<int> bar;

	foo = std::unique_ptr<int>(new int(101));  // rvalue

	bar = std::move(foo);                       // using std::move

	std::cout << "foo: ";
	if (foo) std::cout << *foo << '\n'; else std::cout << "empty\n";

	std::cout << "bar: ";
	if (bar) std::cout << *bar << '\n'; else std::cout << "empty\n";

	return 0;
}

/
// reference: http://www.cplusplus.com/reference/memory/unique_ptr/release/
int test_unique_ptr11()
{
	std::unique_ptr<int> auto_pointer(new int);
	int * manual_pointer;

	*auto_pointer = 10;

	manual_pointer = auto_pointer.release();
	// (auto_pointer is now empty)

	std::cout << "manual_pointer points to " << *manual_pointer << '\n';

	delete manual_pointer;

	return 0;

}

///
// reference: http://www.cplusplus.com/reference/memory/unique_ptr/swap/
int test_unique_ptr12()
{
	std::unique_ptr<int> foo(new int(10)), foo2(new int(10));
	std::unique_ptr<int> bar(new int(20)), bar2(new int(20));

	foo.swap(bar);
	std::cout << "foo: " << *foo << '\n';
	std::cout << "bar: " << *bar << '\n';

	std::swap(foo2, bar2);
	std::cout << "foo2: " << *foo2 << '\n';
	std::cout << "bar2: " << *bar2 << '\n';

	return 0;
}


void math_add(int* a)
{
	int b = ++(*a);
	delete a;
	fprintf(stdout, "add operation: %d\n", b);
}

void math_subtract(int* a)
{
	int b = --(*a);
	delete a;
	fprintf(stdout, "subtraction operation: %d\n", b);
}

int test_unique_ptr13()
{
	{
		std::unique_ptr<int, decltype(&math_add)> A(new int, &math_add);
		if (!A) {
			fprintf(stderr, "A is nullptr\n");
			return -1;
		}

		*A = 10;
	}

	{
		typedef std::unique_ptr<int, std::function<void(int*)>> Oper;

		Oper A(new int, math_add);
		*A = 10;

		Oper B(new int, math_subtract);
		*B = 10;
	}

	return 0;
}

} // namespace unique_ptr_

GitHub:https://github.com/fengbingchun/Messy_Test

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++11中unique_ptr的使用 的相关文章

  • 生成随机、唯一的值 C#

    我已经搜索了一段时间并一直在努力找到这个 我试图用 C 生成几个随机的 唯一的数字 我在用着System Random 我正在使用DateTime Now Ticks seed public Random a new Random Date
  • android.os.Build.SERIAL 是唯一的吗?

    我想为适用于手机和平板电脑的 Android 设备使用唯一的 ID IMEI 不适用于没有 SIM 卡的设备 有时 MAC 地址返回 null 我不确定 android os Build SERIAL 是否唯一 有人知道这件事吗 谢谢 问候
  • Javascript:确定字符串中的所有字符是否唯一,如果不唯一,则删除重复字符

    设置一个数组a letter occurences 但努力循环遍历这个数组 以检查occurences gt 1并删除那些存在的 function charFreq s var i j var a new Array for j 0 j l
  • vba:从数组中获取唯一值

    有没有内置的功能vba questions tagged vba从一维数组中获取唯一值 只删除重复项怎么样 如果没有 那么我如何从数组中获取唯一值 这个帖子 http www vbaexpress com forum showthread
  • Excel为动态下拉列表创建数据验证唯一项,无需新列

    我的表随着数据刷新而增长的列表如下 Balham Halfords P83690 Balham Halfords P83690 Gloucester Durham St P83680 Gloucester Durham St P83680
  • 查找数据库表的唯一约束

    我正在尝试使用 Java 查找表的唯一约束 在 Oracle 数据库上 但这应该没有区别 我找到了一种发现表主键的方法 这要归功于 DatabaseMetaData 的 getPrimaryKeys 然而 我无法找到表格的独特约束 互联网也
  • Unique 不再使用键作为默认值

    我主要在 Mac 中使用 Rstudio 最近我不得不开始使用Windows 但是 我发现 unique 不根据键在 data table 中提供唯一行 这是一个例子 a c 2 3 3 3 3 5 6 7 b c a a f g a d
  • R:如何根据另一个变量中的值选择 dplyr::distinct() 保留哪一行?

    现实生活中的问题 我的受试者有 MRI 扫描数据 其中一些已被扫描多次 单独的行 其中一些每次都是根据不同的协议进行扫描的 我想按主题 ID 保留所有唯一行 如果主题是在两种不同的协议下扫描的 我希望它更喜欢其中一种 玩具示例 librar
  • 删除结构 C++ 向量中的重复项

    我有以下结构 我想将结构存储在向量中 其次我想删除 context 我究竟做错了什么 include
  • 两个字段的唯一约束及其相反

    我有一个数据结构 必须在其中存储元素对 每对恰好有 2 个值 因此我们使用一个表 其中包含字段 左值 右值 这些对应该是唯一的 如果密钥发生更改 它们将被视为相同 Example Fruit Apple is the same as App
  • 查询超慢...我做错了什么?

    你们太棒了 在过去的几天里 我已经在这里发帖两次 作为一个新用户 我对这些帮助感到震惊 因此 我想我应该采用软件中最慢的查询 看看是否有人可以帮助我加快速度 我使用此查询作为视图 因此速度快很重要 但事实并非如此 首先 我有一个联系人表 用
  • 熊猫标签重复

    给定以下数据框 import pandas as pd d pd DataFrame label 1 2 2 2 3 4 4 values 3 5 7 2 5 8 3 d label values 0 1 3 1 2 5 2 2 7 3 2
  • 如何在 Google Cloud Firestore 中强制文档字段属性的唯一性

    我有以下数据 如图所示 我想确保用户名字段是唯一的 我怎样才能强制执行呢 请记住 我的文档 ID 已经是唯一的 我不想使用我的用户名作为文档 ID 无法在 Firestore 中强制执行字段的唯一值 您可以保证的唯一唯一性是集合中的文档 I
  • 在此示例中,“折叠为唯一的‘x’值”是什么意思?

    下面的示例图会产生有关以下内容的警告 In regularize values x y ties missing ties na rm na rm collapsing to unique x values 我无法弄清楚这在我的例子中意味着
  • postgresql 分区上的唯一索引

    我有一个名为 cdrs 的表 CREATE TABLE cdrs i cdr bigint NOT NULL i cdrs connection bigint NOT NULL i call bigint NOT NULL customer
  • 生成指定数量的随机但独特的颜色

    我想做的是给 listView 中的每个项目赋予唯一的颜色 所以我的列表视图中的项目数为 计数 我的方法是调用下面的方法并给出我的项目的方法编号 然后它应该有一个保存第一种颜色的数组 然后当要生成下一个颜色时 应该将其与数组中之前的颜色进行
  • 数据表 DT[i, j, by] 不使用 i 中的条件选择组,而是尝试过滤组内唯一值的数量

    我不确定我的数据发生了什么 也许我遗漏了一些简单的东西 我的数据集有一个 id dSc 和分配给每个 id 的簇 点 我想过滤掉那些只分配了一个簇的 id e g BS 100021 has only 1 cluster point ass
  • 根据 C# 的属性之一从列表中删除重复的项目

    我有类型类别的列表 public class MyClass public SomeOtherClass classObj public string BillId public List
  • 按组添加ID列[重复]

    这个问题在这里已经有答案了 我想根据两列纬度和经度在 R 中创建一个唯一 ID 以便重复的位置具有相同的集群 ID 例如 LAT LONG Cluster ID 13 5330 15 4180 1 13 5330 15 4180 1 13
  • Postgresql 强制执行唯一的双向列组合

    我正在尝试创建一个表 该表将在两个方向上强制执行相同类型的两列的唯一组合 例如 这是非法的 col1 col2 1 2 2 1 我已经想出了这个 但它不起作用 database gt d friend Table public friend

随机推荐

  • SBUS调试助手 sbus解析,sbus协议

    最近在做一个无人机用的四路的开关 即航模遥控器PWM信号控制四路继电器 设计硬件的时候专门用了一路可以配置成串口输入的管脚 外部加了一路施密特反相器 其实主要是滤波防止信号抖动 当然私心就是后续可以接SBUS信号 接触航模遥控器时间挺长了
  • Android WebView 网页使用本地字体

    要求在网页里面调用android app中assets目录下的某个字体文件 网页加载通常有两种方式 xff1a 1 loadDataWithBaseURL 2 loadUrl 一 loadDataWithBaseURL 网页中直接使用fil
  • 若依前后端分离版,图片上传后无法显示问题

    若依前后端分离版 xff0c 部署时通常会采用Nginx做反向代理 访问图片出现404 Not Found问题 若依在文件上传成功后 xff0c 请求访问后台地址会根据profile进行匹配 xff0c 需要自己配置代理 配置方式一 xff
  • Vue项目使用history模式,打包部署到二级目录

    需求 xff1a Vue项目使用history模式 xff0c 打包部署到服务器上的二级目录 示例 xff1a your host name h5 index html 原理 xff1a 把页面地址所有含有 h5 的url重定向到 xff1
  • Springboot 服务jar的外部指定端口和文件方式

    在命令行中指定启动端口 java jar xxx jar server port 61 9000 在命令行中指定启动端口与配置文件 java jar xxx jar server port 61 8980 spring profiles a
  • 【Android】本地图片选择(打开媒体库,选择图片)

    在此调查中我要实现的是 xff1a 点击Pictures 按钮后 xff0c 获取手机内所有图片 xff0c 选择某一个图片 xff0c 并显示到ImageView中 应用范围 xff1a 图片上传时的图片选择 xff0c 类似 34 浏览
  • 【Android】获取手机中已安装apk文件信息(PackageInfo、ResolveInfo)(应用图片、应用名、包名等)

    众所周知 xff0c 通过PackageManager 可以获取手机端已安装的apk 文件的信息 xff0c 具体代码如下 PackageManager packageManager 61 this getPackageManager Li
  • 【Android】状态栏通知Notification、NotificationManager详解

    在Android系统中 xff0c 发一个状态栏通知还是很方便的 下面我们就来看一下 xff0c 怎么发送状态栏通知 xff0c 状态栏通知又有哪些参数可以设置 xff1f 首先 xff0c 发送一个状态栏通知必须用到两个类 xff1a N
  • 【Android动画】之Tween动画 (渐变、缩放、位移、旋转)

    Android 平台提供了两类动画 一类是Tween动画 xff0c 就是对场景里的对象不断的进行图像变化来产生动画效果 xff08 旋转 平移 放缩和渐变 xff09 第二类就是 Frame动画 xff0c 即顺序的播放事先做好的图像 x
  • 面试题之Linux58个面试常问【附带答案】

    面试题之Linux58问 目录 1 Linux常用的发行版 2 在Linux里面查看指定时间段的日志文件 3 将文件中所有的old字符以new代替 4 修改文件中第n行到第m行以new代替old 5 统计字符串在文件中出现的次数 6 查看文
  • 【Android布局】在程序中设置android:gravity 和 android:layout_Gravity属性

    在进行UI布局的时候 xff0c 可能经常会用到 android gravity 和 android layout Gravity 这两个属性 关于这两个属性的区别 xff0c 网上已经有很多人进行了说明 xff0c 这边再简单说一下 资料
  • 我的2011年终总结(流水账篇)

    2011即将过去 xff0c 2012即将到来 2013应该还会如期而来吧 xff1f 2011回顾 xff1a 去日本出差很幸运的遇上了大地震 xff08 还好不在福岛 xff09 和老婆谈了7年了 xff08 认识十年了 xff09 儿
  • poll函数详解及原理

    poll函数实现和select极为相似 xff0c 但是它们的接口并不相同 xff1a int poll struct pollfd fdarray nfds t nfds int timeout int select int maxfdp
  • 深度学习中的优化算法之SGD

    之前在https blog csdn net fengbingchun article details 75351323 介绍过梯度下降 xff0c 常见的梯度下降有三种形式 xff1a BGD SGD MBGD xff0c 它们的不同之处
  • CMake中include_directories的使用

    CMake中include directories命令用于在构建 build 中添加包含目录 其格式如下 include directories AFTER BEFORE SYSTEM dir1 dir2 将给定的目录添加到编译器 comp
  • CMake中target_link_libraries的使用

    CMake中的target link libraries命令用于指定链接给定目标和 或其依赖项时要使用的库或标志 来自链接库目标的使用要求将被传播 propagated 目标依赖项的使用要求会影响其自身源代码的编译 其格式如下 xff1a
  • CMake中install的使用

    CMake中的install命令用于指定安装时要运行的规则 xff0c 其格式如下 xff1a install TARGETS targets EXPORT lt export name gt RUNTIME DEPENDENCIES ar
  • 相机的内参和外参介绍

    注 xff1a 以下相机内参与外参介绍除来自网络整理外全部来自于 视觉SLAM十四讲从理论到实践 第2版 中的第5讲 xff1a 相机与图像 xff0c 为了方便查看 xff0c 我将每节合并到了一幅图像中 相机与摄像机区别 xff1a 相
  • Linux下常用的C/C++开源Socket库

    1 Linux Socket Programming In C 43 43 http tldp org LDP LG issue74 tougher html 2 ACE http www cs wustl edu schmidt ACE
  • C++11中unique_ptr的使用

    在C 43 43 中 xff0c 动态内存的管理是通过一对运算符来完成的 xff1a new xff0c 在动态内存中为对象分配空间并返回一个指向该对象的指针 xff0c 可以选择对对象进行初始化 xff1b delete xff0c 接受